2021-03-25 狂神说Java之 JavaSE学习

常见的DOS命令

打开CMD的方式
1、开始+系统+命令提示符
2、win + R 输入cmd 打开控制台
3、在任意文件夹下面,按住 shift +鼠标右键点击,在此处打开命令行窗口
4、资源管理器的地址栏前面加上 cmd 路径
管理员方式运行:选择以管理员运行的 方式(可以得到最高权限)

  • 关于目录切换命令:
# 盘符切换
C:\Users\XXX> D:
D:\>

# 常看当前目录下的所有文件
D:\> dir
 驱动器 D 中的卷没有标签。
 卷的序列号是 9E77-CA9C
 D:\ 的目录
2019/02/18  16:04    <DIR>          1111
2020/10/17  22:34    <DIR>          AE磁盘缓存
2021/03/09  19:35    <DIR>          bootstrap4模版
2020/09/18  21:30    <DIR>          Eclipse
2021/03/21  20:23    <DIR>          javaproject

# 切换目录  cd change directory
cd /d f: 				# /d 参数实现跨盘符切换
D:\> cd /d f:\bee
f:\bee>

# 返回上级目录
f:\bee>cd ..
f:\>

# 进入同级目录
f:\> cd bee
f:\bee>
f:\bee> cd xunlei
f:\bee\xunlei>
  • 清理屏幕
# cls 清理屏幕  (clear screen)
f:\bee\xunlei> cls
  • 退出终端
exit
  • 查看电脑ip
ipconfig
  • 打开应用程序
calc  		# 打开计算器
mspaint		# 打开画图工具
notepad		# 打开记事本
  • ping命令
ping www.baidu.com
  • 文件操作
C:\Users\xxx>cd /d C:\Users\xxx\Desktop
C:\Users\xxx\Desktop>md test			# 创建文件夹  md 目录名
C:\Users\xxx\Desktop>cd test			# 进入文件夹 
C:\Users\xxx\Desktop\test>cd>a.txt		# 创建文件 a.txt  cd> 文件名
C:\Users\朱鸿君\Desktop\test>del a.txt	# 删除文件		del 文件名
C:\Users\朱鸿君\Desktop\test>cd ..
C:\Users\朱鸿君\Desktop>rd test  		# 移除文件夹	rd 目录名

java入门

三高:高可用、高性能、高并发

Java特性和优势:

  • 简单性
  • 面向对象
  • 可移植
  • 高性能
  • 分布式
  • 动态性
  • 多线程
  • 安全性
  • 健壮性

java三大版本

  • JavaSE:标准版(桌面程序,控制台开发)
  • javaME:嵌入式
  • javaEE:E企业级开发(web端,服务器开发)

JDK JRE JVM

  • jdk:java development kit. 开发者工具
  • JRE:Java runtime environment 运行时环境
  • JVM:Java virtual machine 虚拟机

安装开发

  • 卸载jdk
    - 删除Java安装的目录
    - 删除JAVA_HOME
    - 删除path下关于Java的目录
    - 查看java -verison
  • 安装JDK
    - 百度搜索JDK8,找到下载地址
    - 同意协议,下载电脑对应版本
    - 双击安装jdk
    - 记住安装的路径
    - 配置环境变量
    - 我的电脑-> 系统属性-> 环境变量->JAVA_HOME->配置path变量(%JAVA_HOME%\bin;%JAVA_HOME\jre\bin%)
    - 测试JDK是否安装成功 java -verison

helloworld 详解

public class Hello{
    
    
		public static void main (String[] arges){
    
    
			System.out.print("hello")
		}
}

文件名和类名保持一致
编译:javac Hello.java 生成 class 文件
运行:java Hello 运行class文件

java 基础语法

注释

  • 单行注释. //
  • 多行注释 /* 注释 */
  • 文档注释 /** 注释 */
public class HelloWorld {
    
    
    /**
     * 文档注释
     * @param args
     */
    public static void main(String[] args) {
    
    
        // 单行注释
        System.out.println("hello");
        /*
        多行注释
         */
    }
}

标识符

  • 关键字在这里插入图片描述
  • 类名、变量名、方法名都被称为标识符。
  1. 所有标识符都应该以字母(A-Z/a-z)、美元符($)、下划线(_)开始
  2. 首字母之后可以是字母(A-Z/a-z)、美元符($)、下划线(_)、数字的任何字符组合
  3. 不能使用关键字作为变量名或方法名
  4. 标识符是大小写敏感

数据类型

  • 强类型语言
    • 要求变量的使用严格符合规定,所有变量都必须先定义后才能使用
  • 弱类型语言

Java 的数据类型分为两大类

  • 基本类型
  • 引用类型
    在这里插入图片描述

什么是字节

位(bit):计算机 内部数据 储存的最小单位,11001100是一个八位二进制

字节(byte):计算机中 数据处理 的基本单位,习惯上用大写B来表示

  • 1B(byte)= 8 bit (位)
  • 1024B =1KB
  • 1024KB = 1M
  • 1024M = 1G
  • 1024G = 1TB

字符:计算机中使用的字母、数字、字和符号

面试题

整数拓展: 进制 二进制 0b 十进制 八进制 0 十六进制 0x

 int i = 10;
 int i2= 010;        // 8进制   8
 int i3 =0x10;       // 16进制  0~9 A-F 16

浮点数拓展:

  • float 有限 离散 舍入误差 大约 接近但不等于
  • 最好完全使用浮点数进行比较
// 浮点数拓展:
// 银行业务 ?
// BigDecimal 数学工具类
// float  有限  离散  舍入误差  大约     接近但不等于
// double
// 最好完全使用浮点数进行比较  最好完全使用浮点数进行比较  最好完全使用浮点数进行比较
float f = 0.1f;// 0.1
double d = 0.1;// 0.1
System.out.println(f==d);// false

float d1 = 23232323f;
float d2 = d1+1;
System.out.println(d1==d2);// true

字符拓展:所有的字符本质还是数字

char c1 = 'a';
char c2 = '中';
System.out.println((int)c1);// 97
System.out.println((int)c2);// 20013
// 所有的字符本质还是数字
// 编码 Unicode:97 = a ;65 = A  2字节   0-65536

char c3 = '\u0061';
System.out.println(c3);//a

转义字符:

// 转义字符
// \t     制表符
// \n     换行
System.out.println("hello\tworld");

字符串:

// 字符串(对象,从内存分析)
String sc = new String("hello");
String sd = new String("hello");
System.out.println(sc==sd); // false

String sc2 = "hello";
String sd2 = "hello";
System.out.println(sc2==sd2);//true

布尔值拓展:

boolean flag= true;
if(flag){
    
    } // 老手
if(flag == true){
    
    }; // 新手

类型转换

在这里插入图片描述

  • 强制类型转换:(类型)变量名 高–>低
int i = 128;
byte b= (byte)i;// 内存溢出 -128~127
// 强制转换 
System.out.println(i);// 128
System.out.println(b);//-128
  • 自动类型转换:低–>高
int i = 128;
// 自动转换  低--》高
double c =i;
System.out.println(c);// 128.0

char d = 'a';
int e = d+1;
System.out.println(e); // 98
System.out.println((char)e); // b

注意点:

1、不能对布尔类型进行转换

2、不能把对象类型转换成不相干的类型

3、在把高容量转换到低容量的时候,强制转换

4、转换的时候可能存在内存溢出,或着精度问题

System.out.println((int) 23.7); // 23
System.out.println((int) -45.89f); //-45

转换时的问题

操作比较大的时候,注意溢出问题

// JDK7 新特性  数字之间可以用下划线分割
int money = 10_0000_0000;
int years = 20;
int total = money * years;
System.out.println(total); // -1474836480  计算时溢出

long total2 = money * years; // 默认是int,转换之前已经存在问题了
System.out.println(total2);// -1474836480

long total3 = money *((long)years); // 先把一个数转换成long
System.out.println(total3);// 2000000000

// L l 

变量、常量、作用域

变量

可以变化的量

  • Java每个变量都必须声明其类型
  • Java变量是程序中最基本的存储单元,包括变量名、变量类型和作用域

在这里插入图片描述

// int a b c
// int a=1,b=2,c=3; //程序可读性
String name = "123";
char x = 'x';
double pi = 3.14;

注意:

  • 每个变量都有类型,类型可以是基本类型,也可以是引用类型
  • 变量名必须是合法的标识符
  • 变量声明是一条完整的语句,因此每一个声明都必须以分号结束

变量作用域

  • 类变量
  • 实例变量
  • 局部变量
public class Variable{
    
    
  // 属性:变量
  static int allClick = 0; // 类变量  static :从属于类
  // 实例变量:从属于对象;如果不自行初始化,就是这个类型的默认值 0 0.0
  // boolean 默认是false
  // 除了基本类型,其余的默认值都是null
  String str = "hello"; 
  public void method(){
    
    
    int i = 0; // 局部变量:必须声明和初始化值
  }
  
   // main方法
    public static void main(String[] args) {
    
    
        // 局部变量:必须声明和初始化值
        int i = 10;
        System.out.println(i);

        Demo08 demo08 = new Demo08();
        System.out.println(demo08.str);

        System.out.println(allClick);
    }

    // 其他方法
    public void add(){
    
    

    }
}

变量的命名规范

  • 所有变量、方法、类名:见名知意
  • 类成员变量:首字母小写和驼峰原则:monthSalary,除第一个单词以外,其他单词首字母大写
  • 局部变量:首字母小写和驼峰原则
  • 常量:大写字母和下划线:MAX_VALUE
  • 类名:首字母大写和驼峰原则:Man,GoodMan
  • 方法名:首字母小写和驼峰原则:runRun()

常量

常量:初始化后不能再改变值!不会变动的值

  • 一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变
  • 常量名一般使用大写字符
final 常量名 =;

public class Demo09 {
    
    
    // 修饰符,不存在先后顺序
    static final double PI = 3.14;
    // final static double PI = 3.14;

    public static void main(String[] args) {
    
    
        System.out.println(PI);
    }
}

运算符

算数运算符:+ ,-,*,/,%(取余/模),++,–

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        // 二远运算符
        // ctrl+d 复制当前行到下一行
        int a = 10;
        int b = 20;
        int c = 25;
        int d = 25;

        System.out.println(a+b);
        System.out.println(a-b);
        System.out.println(a*b);
        System.out.println(a/(double)b);// 0.5  小心作用范围
    }
}

public class Demo02 {
    
    
    public static void main(String[] args) {
    
    
        long a = 123123123123123L;
        int b =123;
        short c = 10;
        byte d =8;

        System.out.println(a+b+c+d); // long
        System.out.println(b+c+d); // int
        System.out.println(c+d); // int 默认是int类型
        System.out.println((double)c+d); // double
    }
}

public class Demo03 {
    
    
    public static void main(String[] args) {
    
    
        int a = 10;
        int c = 21;

        // 取余,模运算
        System.out.println(c%a);// 21/10=2···1
    }
}

// 重要!!!
public class Demo04 {
    
    
    public static void main(String[] args) {
    
    
        // ++ -- 自增,自减  一元运算符
        int a = 3;
        int b = a++; // 执行完这行代码后,先给b赋值,再自增
        // a++ a=a+1;
        System.out.println(a);// 4
        // a++ a=a+1;
        int c = ++a; // ++a  a=a+1  执行完这段代码前,先给a自增,再给c赋值

        System.out.println(a);// 5
        System.out.println(b);// 3
        System.out.println(c);// 5

        // 幂运算 2^3 2*2*2=8  很多运算需要使用工具类来操作
        double d=Math.pow(2,3);//8
        System.out.println(d);
    }
}

赋值运算符:=
关系运算符:>,<,>=,<=,==,!=,instanceof

public class Demo03 {
    
    
    public static void main(String[] args) {
    
    
        // 关系运算符返回的结果:正确,错误  boolean
        int a = 10;
        int b= 20;
        
        System.out.println(a>b);//false
        System.out.println(a<b);//true
        System.out.println(a==b);// false
        System.out.println(a!=b);// true
    }
}

逻辑运算符:&&(与),||(或),!(非)

 public class Demo05 {
    
    
     public static void main(String[] args) {
    
    
         boolean a = true;
         boolean b = false;
 
         System.out.println(a&&b);// false  逻辑与运算,两个变量都为真,结果才为真
         System.out.println(a||b); // true  逻辑或运算,两个都为假,结果才是假
         System.out.println(!(a&&b));// true 如果是真,则为假
 
         // 短路运算
         int c = 5;
         boolean d = (c<4)&&(c++<4);
         System.out.println(d);// false
         System.out.println(c);// 5
     }
 }

位运算符:&,|,^,~,>>,<<,>>>

public class Demo06 {
    
    
    public static void main(String[] args) {
    
    
        /**
         * A= 0011 1100
         * B= 0000 1101
         * A&B = 0000 1100 如果都是1 则为1,否则为0
         * A|B = 0011 1101 如果都是0,则为0,否则为1
         * A^B = 0011 0001 如果相同为0,不同为1
         * ~B  = 1111 0010 取反
         *
         * 面试题 2*8怎么算最快 2*2*2*2
         * 左移 << *2
         * 右移 >> /2
         */
        System.out.println(2<<3); // 16

        /**
         * 0000 0000  0
         * 0000 0001  1
         * 0000 0010  2
         * 0000 0011  3
         * 0000 0100  4
         * 0000 1000  8
         * 0001 0000 16
         */
    }
}
  • 条件运算符 :?:
public class Demo08 {
    
    
    public static void main(String[] args) {
    
    
        // x ? y : z
        // 如果x==true,则结果为y,否则为z
        
        int score = 80;
        String type = score < 60 ? "不及格":"及格";
    }
}
  • 扩展赋值运算符:+=,-=,*=,/=
public class Demo07 {
    
    
    public static void main(String[] args) {
    
    
        int a = 10;
        int b = 20;

        a+=b;// a = a+b
        a-=b;// a = a-b
        System.out.println(a);//30

        // 字符串连接符 + string
        System.out.println(a+b);//30
      	// 注意!!!
        System.out.println(""+a+b); // 1020
        System.out.println(a+b+"");//  30
    }
}

优先级

http://c.biancheng.net/view/794.html

包机制

一般利用公司域名倒置作为包名

// 导入这个包下所有的类
import com.kuang.base.*

JAVADoc生成文档

在线API帮助文档https://docs.oracle.com/javase/8/docs/api/

Javadoc命令是用来生成自己API文档的
参数信息

  • @author 作者名
  • @version 版本号
  • @since 指明需要最早使用的jdk版本号
  • @param 参数名
  • @return 返回值情况
  • @throws 异常抛出情况
# 命令行生成
javadoc -encoding UTF-8 -charset UTF-8 Doc.java

IDEA 生成Javadoc文件

首先选择需要生成文档的代码
在这里插入图片描述
然后点击Tools—> Generate javaDoc
在这里插入图片描述
-encoding utf-8 -charset utf-8在这里插入图片描述
点击ok,就生成javadoc文档
在这里插入图片描述

Java 流程控制

用户交互Scanner

Scanner 对象

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        // 创建一个扫描器对象,用于接收键盘数据
        Scanner scanner = new Scanner(System.in);

        System.out.println("使用next方式接收:");

        // 判断用户有没有输入字符串
        if(scanner.hasNext()){
    
    
            // 使用 next 方式接收
            String str = scanner.next();// 程序会等待用户输入完毕
            System.out.println("输入的内容为:"+str);
        }
        // 凡是属于IO流的类,如果不关闭会一直占用资源,要养成好习惯用完就关掉
        scanner.close();
    }
}

在这里插入图片描述

  • next()
    • 一定要读取到有效字符后才可以结束输入
    • 对输入有效字符之前遇到的空白,next()方法会自动将其去掉
    • 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
    • next()不能得到带有空格的字符串
public class Demo02 {
    
    
    public static void main(String[] args) {
    
    
        // 从解盘接收数据
        Scanner scanner= new Scanner(System.in);

        System.out.println("使用next方式接收:");

        // 判断是否还有输入
        if(scanner.hasNextLine()){
    
    
            // 程序会等待用户输入
           String str =  scanner.nextLine();
           System.out.println("输入的内容为:"+str);
        }
        scanner.close();
    }
}

在这里插入图片描述

  • nextLine()
    • 以Enter (回车)为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符
    • 可以获得空白
public class Demo03 {
    
    
    public static void main(String[] args) {
    
    
        // 从解盘接收数据
        Scanner scanner= new Scanner(System.in);
        System.out.println("请输入数据:");
        String str = scanner.nextLine();
        System.out.println("输入的内容为:"+str);
        scanner.close();
    }
}

在这里插入图片描述
输入整数和小数:

public class Demo04 {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        // 从键盘接收数据
        int i = 0;
        float f= 0.0f;
        System.out.println("请输入整数:");

        if(scanner.hasNextInt()){
    
    
            i = scanner.nextInt();
            System.out.println("整数数据:"+i);
        }else{
    
    
            System.out.println("输入的不是整数数据");
        }

        System.out.println("请输入小数:");

        if(scanner.hasNextFloat()){
    
    
            f = scanner.nextFloat();
            System.out.println("小数数据:"+f);
        }else{
    
    
            System.out.println("输入的不是小数数据");
        }
        scanner.close();
    }
}

在这里插入图片描述
我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果:

public class Demo05 {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        // 和
        double sum = 0;
        // 计算输入多少个数字
        int m = 0;

        // 通过循环判断是否还有输入,并在里面对每一次进行求和统计
        while (scanner.hasNextDouble()){
    
    
           double x = scanner.nextDouble();
           System.out.println("你输入了第"+m+"个数据,然后当前结果sum="+sum);
           m = m+1;// m++
           sum = sum +x;
        }
        System.out.println(m+"个数的和为:"+sum);
        System.out.println(m+"个数的平均值为:"+(sum/m));
        scanner.close();
    }
}

在这里插入图片描述

顺序结构

java的基本结构就是顺序结构,除非特别指明,否则就是按照顺序一句一句执行

  public static void main(String[] args) {
    
    
        System.out.println("hello1");
        System.out.println("hello2");
        System.out.println("hello3");
    }

语句与语句之间,框与框之间是按从上到下的顺序进行的,他是由若干个依次执行的处理步骤组成的,是任何一个算法都离不开的一种基本算法结构

选择结构

if 选择结构

if单选择结构

需要判断一个东西是否可行,然后我们才去执行,这样的一个过程在程序中用if语句来表示
在这里插入图片描述
语法:

if(布尔表达式){
    
    
	// 如果布尔表达式为true将执行的语句
}
public class IfDemo01 {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入内容:");
        String s = scanner.nextLine();
        // equals :判断字符串是否相等
        if(s.equals("hello")){
    
    
            System.out.println(s);
        }
        System.out.println("End");
        scanner.close();
    }
}

if双选择结构

需要有两个判单,需要一个双选择结构,if-else
在这里插入图片描述

if(布尔表达式){
    
    
	// 如果布尔表达式为true将执行的语句
}else{
    
    
	// 如果布尔表达式为false将执行的语句
}

public class IfDemo02 {
    
    
    public static void main(String[] args) {
    
    
        // 考试分数大于60及格,小于60不及格

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入成绩:");
        int score = scanner.nextInt();
        if(score>=60){
    
    
            System.out.println("及格");
        }else{
    
    
            System.out.println("不及格");
        }
        scanner.close();
    }
}

if多选择结构

if(布尔表达式1{
    
    
	// 如果布尔表达式1为true将执行的语句
}else if(布尔表达式2){
    
    
	// 如果布尔表达式2为true将执行的语句
}else if(布尔表达式3){
    
    
	// 如果布尔表达式3为true将执行的语句
}else{
    
    
	// 如果以上布尔表达式都不为true将执行的语句
}

public class IfDemo03 {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入成绩:");
        int score = scanner.nextInt();
        if(score==60){
    
    
            System.out.println("满分");
        }else if(score<100 && score>=90){
    
    
            System.out.println("A");
        }else if(score<90 && score>=80) {
    
    
            System.out.println("B");
        }else if(score<80 && score>=70) {
    
    
            System.out.println("C");
        }else if(score<70 && score>=60) {
    
    
            System.out.println("D");
        }else{
    
    
            System.out.println("不及格");
        }
        scanner.close();
    }
}

嵌套的if结构

if(布尔表达式1{
    
    
	// 如果布尔表达1式为true将执行的语句
	if(布尔表达式2{
    
    
	// 如果布尔表达式2为true将执行的语句
	}
}

switch多选择结构

判断一个变量与一系列值中的某个值是否相等,每个值称为一个分支

switch(exprssion){
    
    
	case value:
		// 语句
		break;//可选
	case value:
		// 语句
		break; // 可选
	default:// 可选
		// 语句
}

public class SwitchDemo01 {
    
    
    public static void main(String[] args) {
    
    
        char grade = 'c';
        // case 穿透
        // switch 匹配一个具体的值
        switch (grade){
    
    
            case 'a':
                System.out.println("优秀");
                break; // 可选
            case 'b':
                System.out.println("良好");
                break;
            case 'c':
                System.out.println("及格");
                break;
            default:
                System.out.println("不及格");
        }
    }
}

switch 语句中的变量类型可以是:

  • byte,short,int,char
  • 从JavaSE7开始,switch支持字符串String类型
  • 同时case 标签必须为字符串常量或字面量
public class SwitchDemo02 {
    
    
    public static void main(String[] args) {
    
    
        String name = "狂神";

        switch (name){
    
    
            case "wer":
                System.out.println("wer");
                break;
            case "狂神":
                System.out.println("ks");
                break;
            default:
                System.out.println("???");
        }
    }
}
public class SwitchDemo02 {
    
    
    public static void main(String[] args) {
    
    

        String name = "狂神";
        // JDk7的新特性,表达式结果可以是字符串
        // 字符的本质还是数字
        switch (name){
    
    
            case "wer":
                System.out.println("wer");
                break;
            case "狂神":
                System.out.println("ks");
                break;
            default:
                System.out.println("???");
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTDfDGV7-1616679866926)(/Users/lilithliu/Library/Application Support/typora-user-images/image-20210325100924421.png)]

把class文件放入IDEA 就可以看到反编译后的文件

循环结构

while 循环

while(布尔表达式){
    
    
  // 循环内容
}

只要布尔表达式为true,循环就会一直执行下去

大部分情况是会让循环停止下来的,需要一个表达式失效的方式来结束循环

少部分情况需要循环一直执行,比如服务器的请求响应监听等

尽量避免死循环,会影响程序性能或者造成程序卡死崩溃

public class WhileDemo01 {
    
    
    public static void main(String[] args) {
    
    
        // 输出1—100
        int i=0;
        while (i<100){
    
    
            i++;
            System.out.println(i);
        }
    }
}

public class WhileDemo02 {
    
    
    public static void main(String[] args) {
    
    
        // 死循环
       while (true){
    
    
           // 等待客户端链接
           // 定时检查
           // ···
       }
    }
}

思考:1+2+···+100=?

public class WhileDemo03 {
    
    
    public static void main(String[] args) {
    
    
        
        int i = 0;
        int sum = 0;
        while (i <= 100) {
    
    
            sum = sum + i;
            i++;
        }
        System.out.println(sum);//5050
    }
}

do while 循环

至少会执行一次

do{
    
    
  //代码语句
}while(布尔表达式);

while与do-while的区别:

  • While 先判断后执行,do-while先执行后判断
  • Do-while总是保证循环体会被至少执行一次
public class DoWhileDemo01 {
    
    

    public static void main(String[] args) {
    
    

        int i = 0;
        int sum = 0;
        do {
    
    
            sum = sum + i;
            i++;
        } while (i <= 100);
        System.out.println(sum);//5050
    }
}

for循环

for循环语句是支持迭代的一种通用结构,是最有效,最灵活的循环结构

for(初始化;布尔表达式;更新){
    
    
  // 代码语句
}

public class ForDemo01 {
    
    
    public static void main(String[] args) {
    
    
        int a = 1;// 初始化条件

        while(a<=100){
    
    //条件判断
            System.out.println(a);//循环体
            a+=2;// 迭代
        }
        System.out.println("while 循环结束");
        
        // 初始化//条件判断 // 迭代  100.for(IDEA快捷键)
        for(int i =1;i<=100;i++){
    
    
            System.out.println(i);
        }
        System.out.println("for循环结束");
    }
}

说明:

1、最先执行初始化步骤,可以声明一种类型,但可初始化一个或多个循环控制变了,也可以是空语句

for(;i<=100;i++){
    
    
     System.out.println(i);
  }

2、然后检测布尔表达式的值(为true循环体被执行,为false循环终止,开始执行循环体后面的语句)

3、执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)

4、再次检测布尔表达式,循环执行上面的过程

for(;;;){
	// 死循环
}

练习

计算0-100之间的奇数和偶数的和

public class ForDemo02 {
    
    
    public static void main(String[] args) {
    
    
        // 计算0-100之间的奇数和偶数的和
        int oddSum = 0;
        int evenSum = 0;
        for (int i = 0; i <= 100; i++) {
    
    
            if(i%2!=0){
    
     // 基数
                oddSum+=i; // oddsum = oddsum + i
            }else{
    
     // 偶数
                evenSum+=i;
            }
        }
        System.out.println(oddSum);
        System.out.println(evenSum);
    }
}

使用while循环或者for循环输出1-1000之间能被5整除的数,并且每行输出3个

public class ForDemo03 {
    
    
    public static void main(String[] args) {
    
    
        for (int i = 0; i <= 1000; i++) {
    
    
            if(i%5==0){
    
    
                System.out.print(i+"\t");
            }
            if(i%(5*3)==0){
    
    
                System.out.println();
//                System.out.print("\n");
            }
        }
    }
}

打印九九乘法表

public class ForDemo04 {
    
    
    public static void main(String[] args) {
    
    
        // 1、先打印第一列
        // 2、把固定的1再用一个循环包起来
        // 3、去掉重复项,i<=j
        // 4、调整样式
        for (int j = 1; j <= 9; j++) {
    
    
            for (int i = 1; i <= j; i++) {
    
    
                System.out.print(j + "*" + i + "=" + (j * i)+"\t");
            }
            System.out.println();
        }
    }
}

增强for循环

for(声明语句:表达式){
    
    
  //代码句子
}

public class ForDemo05 {
    
    
    public static void main(String[] args) {
    
    
        int[] numbers = {
    
    10, 20, 30, 40, 50};// 定义了一个数组
        
        for (int i = 0; i < 5; i++) {
    
    
            System.out.println(numbers[i]);
        }
        // 遍历数组的元素
        for (int x : numbers) {
    
    
            System.out.println(x);
        }
    }
}

break continue

break 在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)

public class BreakDemo {
    
    
    public static void main(String[] args) {
    
    
        int i = 0;
        while (i<100){
    
    
            i++;
            System.out.println(i);
            if(i==30){
    
    
                break;
            }
        }
      System.out.println("123");
    }
}

continue 语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定

public class ContinueDemo {
    
    
    public static void main(String[] args) {
    
    
        int i=0;
        while (i<100){
    
    
            i++;
            if(i%10==0){
    
    
                System.out.println();
                continue;
            }
            System.out.print(i);
        }
    }
}

public class LableDemo {
    
    
    public static void main(String[] args) {
    
    
        // 打印101-150之间的所有质数
        // 质数是指大于1的自然数中,除了1和它本身意外不再有其他因数的自然数

        int count = 0;
      	// 不建议使用
        outer:for(int i=101;i<150;i++){
    
    
            for(int j=2;j<i/2;j++){
    
    
                if(i%j==0){
    
    
                    continue outer;
                }
            }
            System.out.println(i+"");
        }
    }
}

练习

打印三角形

public class TestDemo01 {
    
    
    public static void main(String[] args) {
    
    
        // 打印5行 三角形
        for (int i = 1; i <= 5; i++) {
    
    
            for(int j = 5;j>=i;j--){
    
    
                System.out.print(" ");
            }
            for(int j = 1;j<=i;j++){
    
    
                System.out.print("*");
            }
            for(int j = 1;j<i;j++){
    
    
                System.out.print("*");
            }
            System.out.println();
        }

    }
}

java 方法详解

概念

Java 方法是语句的集合,他们在一起执行一个功能

  • 方法是解决一类问题的步骤的有序集合
  • 方法包含与类或对象中
  • 方法在程序中被创建,在其他地方被引用
  • == 一个方法只完成一个功能(原子性)==
public class Demo01 {
    
    
    // main 方法
    public static void main(String[] args) {
    
    
        int sum = add(1, 2);
        System.out.println(sum);
    }

    // 加法
    public static int add(int a, int b) {
    
    
        return a + b;
    }
}

方法的定义与调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oBI35KOQ-1616679866928)(/Users/lilithliu/Library/Application Support/typora-user-images/image-20210325132855704.png)]

public static void main(String[] args) {
    //实际参数:实际调用传递给他的参数
    int sum = add(1, 2);
    System.out.println(sum);
}

// 加法
// 形式参数:用来定义作用的
public static int add(int a, int b) {
    return a + b;
}

public class Demo02 {
    public static void main(String[] args) {
        int max =max(10,20);
        System.out.println(max);
    }

    // 比大小
    public static int max(int num1,int num2){
        int result = 0;
        if(num1==num2){
            System.out.println("num1==num2");

            return 0; // 终止方法
        }
        if(num1>num2){
            result = num1;
        }else {
            result = num2;
        }
        return result;
    }
}

值传递(Java) 和 引用传递

java基本数据类型传递与引用传递区别详解

https://blog.csdn.net/javazejian/article/details/51192130

方法的重载

在一个类中,有相同的函数名称,但形参不同的函数

方法的重载规则:

  • 方法名称必须相同
  • 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)
  • 方法的返回类型可以相同也可以不相同
  • 仅仅返回类型不同不足以成为方法的重载

实现理论:

方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。

命令行传参

有时候希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现

public class Demo03 {
    
    
    public static void main(String[] args) {
    
    
        // args.length 数组长度
        for (int i = 0; i < args.length; i++) {
    
    
            System.out.println(args[i]);
        }
    }
}

在这里插入图片描述

可变参数

JDK1.5 开始,Java支持传递同类型的可变参数给一个方法

  • 在制定参数类型后面加一个···
  • 一个方法只能指定一个可变参数,它必须是方法的最后一个参数。
  • 任何普通的参数必须在它之前声明
public class Demo04 {
    
    
    public static void main(String[] args) {
    
    
        Demo04 demo04 = new Demo04();
        // 调用可变参数的方法
        demo04.test(1,2,3,4,5);
    }
    // 本质是数组
    public void test(int x,int... i){
    
    
        System.out.println(i);
        System.out.println(i[0]);
        System.out.println(i[1]);
    }

    public static void printMax(double... numbers){
    
    
        if(numbers.length==0){
    
    
            System.out.println("no argument passed");
            return;
        }
        double result = numbers[0];
        for (int i = 1; i < numbers.length; i++) {
    
    
                if(numbers[i]>result){
    
    
                    result = numbers[i];
                }
        }
        System.out.println("max ="+result);
    }
}

递归讲解

自己调用自己

public class Demo05 {
    
    
    public static void main(String[] args) {
    
    
        Demo05 demo05 = new Demo05();
        demo05.test();
    }
    
    public void test(){
    
    
        test();
    }
}

递归结构包含两个部分:

  • 递归头:什么时候不调用自身方法,如果没有头,将陷入死循环
  • 递归体:什么时候需要调用自身方法
public class Demo06 {
    
    
    // 1! 1
    // 2! 2*1
    // 3! 3*2*1
    public static void main(String[] args) {
    
    
        System.out.println(f(5));
    }
    // 2 2*f(1)
    public static int f (int n ){
    
    
        if(n==1){
    
    
            return 1;
        }else{
    
    
            return n*f(n-1);
        }
    }
}

小计算可以用递归,大运算别用递归,会影响机器性能

Java数组

概述

数组是相同类型数据的有序集合

数组描述的是相同类型的若干个数据,按照一定的先后顺序排列组合而成

数组的声明和创建

public class ArrayDemo01 {
    
    
    // 变量的类型 变量的名字 = 变量的值
    // 数组类型
    public static void main(String[] args) {
    
    
        int[] nums; // 声明一个数组 首选
        int nums2[];

        nums = new int[10];// 创建一个数组

        // 给数组元素中赋值
        nums[0]=1;
        nums[1]=2;
        nums[2]=3;
        nums[3]=4;
        nums[4]=5;
        nums[5]=6;

        System.out.println(nums[0]);
        System.out.println(nums[6]);// 0
        //计算所有元素大的和
        int sum =  0;
        // 获取数组的长度:arrays.length
        for (int i = 0; i < nums.length; i++) {
    
    
            sum =sum +nums[i];
        }
        System.out.println(sum);
    }
}

内存分析

java 内存分析:

  • 堆:
    • 存放new的对象和数组
    • 可以被所有的线程共享,不会存放别的对象引用
  • 栈:
  • 存放基本变量类型(会包含这个基本类型的具体数值)
  • 引用对象的变量(会存放这个引用在堆里面的具体地址)
  • 方法区
    • 可以被所有的线程共享
    • 包含了所有的class和static变量

在这里插入图片描述

三种初始化

静态初始化

动态初始化

public class ArrayDemo02 {
    
    
    public static void main(String[] args) {
    
    
        // 静态初始化:创建 + 赋值
        int[] a = {
    
    1,2,3,4,5};
        System.out.println(a[0]);//1
        
        // 动态初始化: 包含默认初始化
        int[] b = new int [10];
        b[0] = 10;
        System.out.println(b[0]);//10
        System.out.println(b[1]);//0
    }
}

数组的默认初始化

  • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化

数组的四个基本特点

其长度是确定的,数组一旦被创建,大小就是不可以改变的

其元素必须是相同类型,不允许出现混合类型

数组中的元素可以是任何数据类型,包括基本类型和引用类型

数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。

数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中。

数组边界

下标的合法区间是:【0,length-1】

如果越界就会报错:ArrayIndexOutOfBoundsException:数组下标越界异常

数组的使用

普通的for循环

public class ArrayDemo03 {
    
    
    public static void main(String[] args) {
    
    
        int[] arrays = {
    
    1, 2, 3, 4, 5};

        //打印全部的数组元素
        for (int i = 0; i < arrays.length; i++) {
    
    
            System.out.println(arrays[i]);
        }

        // 计算所有元素的和
        int sum = 0;
        for (int i = 0; i < arrays.length; i++) {
    
    
            sum += arrays[i];
        }
        System.out.println(sum);

        // 查找最大元素
        int max = arrays[0];
        for (int i = 1; i < arrays.length; i++) {
    
    
            if (arrays[i] > max) {
    
    
                max = arrays[i];
            }
        }
        System.out.println(max);
    }
}

for-each循环

public static void main(String[] args) {
    
    
    int[] arrays = {
    
    1, 2, 3, 4, 5};
    // jdk1.5 没有下标
    for (int array : arrays) {
    
    
        System.out.println(array);
    }
}

数组作方法入参

public static void main(String[] args) {
    
    
  int[] arrays = {
    
    1, 2, 3, 4, 5};
    printArray(arrays);
}

// 打印数组元素
public static void printArray(int[] arrays) {
    
    
    for (int i = 0; i < arrays.length; i++) {
    
    
        System.out.println(arrays[i]);
    }
}

数组作返回值

public static void main(String[] args) {
    
    
    int[] arrays = {
    
    1, 2, 3, 4, 5};
    
    int[] reverse = reverse(arrays);
    printArray(reverse);
}

// 反转数组
public static int[] reverse(int[] arrays) {
    
    
    int[] result = new int[arrays.length];
    for (int i = 0, j = result.length - 1; i < arrays.length; i++, j--) {
    
    
        result[j] = arrays[i];
    }
    return result;
}

多维数组

在这里插入图片描述

public class ArrayDemo05 {
    
    
    public static void main(String[] args) {
    
    
        /**
         * 1,2  array[0]
         * 2,3  array[1]
         * 3,4  array[2]
         * 4,5  array[3]
         */
        int[][] array = {
    
    {
    
    1, 2}, {
    
    2, 3}, {
    
    3, 4}, {
    
    4, 5}};
        printArray(array[0]);//1,2
        System.out.println(array[0][0]);//1
        System.out.println(array[0][1]);//2
        for (int i = 0; i < array.length; i++) {
    
    
            for (int j = 0; j < array[i].length; j++) {
    
    
                System.out.println(array[i][j]);
            };
        }
        System.out.println(array.length);//4
        System.out.println(array[0].length);//2

    }

    // 打印数组元素
    public static void printArray(int[] arrays) {
    
    
        for (int i = 0; i < arrays.length; i++) {
    
    
            System.out.println(arrays[i]);
        }
    }

}

Arrays类讲解

public class ArrayDemo06 {
    
    
    public static void main(String[] args) {
    
    
        int[] a = {
    
    1,2,3,4,555,4324,21,234};
        
        //打印数组元素
        System.out.println(Arrays.toString(a));
        
        // 排序 升序
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));
      
      	// 填充
        Arrays.fill(a,0);
      
       	// 填充
        Arrays.fill(a,2,4,0);
    }
    
    public void  printArray(int[] a){
    
    
        for (int i = 0; i <a.length ; i++) {
    
    
            if(i==0){
    
    
                System.out.print("[");
            }
            if(i==a.length-1){
    
    
                System.out.print(a[i]+"]");
            }else{
    
    
                System.out.print(a[i]+", ");
            }
        }
    }
}

冒泡排序

1、比较数组中,两个相邻的元素,如果第一个数比第二个数字大,我们就交换他们的位置

2、每一次比较,都会产生出一个最大,或者最小的数字

3、下一轮,可以少一次排序

4、依次循环,直到结束

public class ArrayDemo07 {
    
    
    public static void main(String[] args) {
    
    
        int[] a ={
    
    1,3,2,4,6,5};
        int[] sort = sort(a);
        System.out.println(Arrays.toString(sort));
    }

    // 冒泡排序
    public static int[] sort(int[] array){
    
    
        // 临时变量
        int temp =0 ;
        // 外层循环,判断需要走多少次
        for (int i = 0; i < array.length; i++) {
    
    
            // 内层循环,比较两个数,如果第一个比第二个大,则交换位置
            for (int j = 0; j <array.length-1-i ; j++) {
    
    
                if(array[j+1]>array[j]){
    
    
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1]=temp;
                }
            }

        }
        return array;
    }
}

时间复杂度是O(n2)

如何优化?

package com.kuang.array;

import java.util.Arrays;

public class ArrayDemo07 {
    
    
    public static void main(String[] args) {
    
    
        int[] a ={
    
    1,3,2,4,6,5};
        int[] sort = sort(a);
        System.out.println(Arrays.toString(sort));
    }

    // 冒泡排序
    public static int[] sort(int[] array){
    
    
        // 临时变量
        int temp =0 ;
        // 外层循环,判断需要走多少次
        for (int i = 0; i < array.length; i++) {
    
    
            // 通过flag减少没有意义的比较
            boolean flag = false;
            // 内层循环,比较两个数,如果第一个比第二个大,则交换位置
            for (int j = 0; j <array.length-1-i ; j++) {
    
    
                if(array[j+1]>array[j]){
    
    
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1]=temp;
                    flag = true;
                }
            }
            if(flag==false){
    
    
                break;
            }

        }
        return array;
    }
}

稀疏数组

数据结构

当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方式:

  • 记录数组一共有几行几列,有多少个不同值
  • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序规模(压缩)

在这里插入图片描述

package com.kuang.array;

import java.util.Arrays;

public class ArrayDemo08 {
    
    
    public static void main(String[] args) {
    
    
       // 1、创建一个二维数组 11*11 0:没有棋子 1:黑棋 2:白棋
        int[][] array1 = new int[11][11];
        array1[1][2]=1;
        array1[2][3]=2;
        // 输出原始素组
        for (int[] ints : array1) {
    
    
            for (int anInt : ints) {
    
    
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }

        // 转换为稀疏数组保存
        // 获取有效值的个数
        int sum = 0;
        for (int i = 0; i < 11; i++) {
    
    
            for (int j = 0; j < 11; j++) {
    
    
                if(array1[i][j]!=0){
    
    
                    sum++;
                }

            }
        }
        System.out.println("有效值的个数"+sum);

        //2、创建一个稀疏数组
        int[][] array2 = new int[sum+1][3];
        array2[0][0]=11;
        array2[0][1]=11;
        array2[0][2]=sum;

        // 遍历二维数组,将非0的值,存入稀疏数组
        int cout = 0;
        for (int i = 0; i < array1.length; i++) {
    
    
            for (int j = 0; j < array1[i].length; j++) {
    
    
                if(array1[i][j]!=0){
    
    
                    cout++;
                    array2[cout][0]=i;
                    array2[cout][1]=j;
                    array2[cout][2]=array1[i][j];
                }

            }
        }

        // 输出
        for (int i = 0; i < array2.length; i++) {
    
    
            System.out.println(array2[i][0]+"\t"+array1[i][1]+
                    "\t"+array1[i][2]+
                    "\t");
        }

        // 还原
        // 读取稀疏数组
        int[][] array3 = new int[array2[0][0]][array2[0][1]];

        // 给其中的元素还原他的值
        for (int i = 1; i < array2.length; i++) {
    
    
            array3[array2[i][0]][array2[i][1]]=array2[i][2];
        }
        // 打印
        for (int[] ints : array1) {
    
    
            for (int anInt : ints) {
    
    
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
    }
}

面向对象编程OOP

初识面向对象

面向过程&面向对象

面向过程思想

  • 步骤清晰简单,第一步,第二步
  • 线性思维
  • 面对过程适合处理一些较为简单的问题

面向对象思想

  • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索
  • 面向对象适合处理复杂问题,适合处理需要多人协作的问题

面向对象:

  • 面向对象编程的本质:== 以类的方式组织代码,以对象的组织(封装)数据==
  • 抽象
  • 三大特性:封装,继承,多态(同一个事物有多种形态)
  • 从认识论角度考虑先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象。类是对象的模版

方法回顾和加深

回顾方法的定义

package com.oop.demo01;

import java.io.IOException;

public class Demo01 {
    
    
    // main 方法
    public static void main(String[] args) {
    
    

    }

    /**
     * 修饰符 返回值类型 方法(参数类型 参数名){
     *     //方法体
     *     return 返回值;
     * }
     *  return 结束方法,返回一个结果  break :跳出switch
     */
    public String sayHello(){
    
    
        return "hello";
    }

    public int max(int a, int b ){
    
    
        return a>b ? a : b;// 三元运算符
    }


    public void readFile (String file )throws IOException{
    
    

    }
}

回顾方法的调用

静态方法和非静态方法

public static void main(String[] args) {
    
    
    // 非静态方法  实例化这个类 new
    // 对象类型 对象名 = 对象值
    Student student = new Student();
    student.say();
    // 静态方法
    Student.say2();
}

// 和类一起加载的
public static void a(){
    
    
//   b();
}
// 类实例化之后才会存在
public  void b(){
    
    

}

// 学生类
public class Student {
    
    

    // 静态方法
    public static void say2(){
    
    
        System.out.println("12222");
    }
    // 非静态方法
    public  void say(){
    
    
        System.out.println("12333");
    }
}

形参和实参

public static void main(String[] args) {
    
    
  	// 实际参数和形式参数的类型要对应
    // 实际参数
    new Demo03().add(1,2);
}

//形式参数
public int add(int a,int b){
    
    
    return a+b;
}

值传递和引用传递

package com.oop.demo01;
// 值传递
public class Demo04 {
    
    
    public static void main(String[] args) {
    
    
        int a=1;
        System.out.println(a);// 1

        Demo04.change(a);
        System.out.println(a);// 1
    }

    // 返回值为空
    public static void change(int a){
    
    
        a=10;
    }
}
package com.oop.demo01;
// 引用传递:对象 ,本质还是值传递
public class Demo05 {
    
    
    public static void main(String[] args) {
    
    
        Person person = new Person();
        System.out.println(person.name);// null
        Demo05.change(person);
        System.out.println(person.name);// 123
    }

    // 返回值为空
    public static void change(Person person){
    
    
        // person 是一个对象,指向的 Person person = new Person(); 这是一个具体的人,可以改变属性
        person.name="123";
    }

}

// 定义了一个person类,有一个属性:name
class Person{
    
    
    String name; // null 
}

类与对象的创建

类与对象的关系

类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物

  • 动物、植物
  • person类、car类。这些类都是用来描述/定义一类具体的事物应该具备的特点和行为

== 对象是抽象概念的具体实例 ==

  • 能够体现出特点,展现出功能的是具体实例,而不是一个抽象概念
  • 张三是人的一个具体实例

创建与初始化对象

使用new关键字创建对象

  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象 进行默认的初始化 以及对类中构造器的调用
// 学生类
public class Student {
    
    
    // 属性: 字段
    String name;//null
    int age; // 0

    public void study(){
    
    
        // this 指当前这个类
        System.out.println(this.name+"在学习");
    }
}

// 一个项目应该只存在一个main方法
public class Application {
    
    
    public static void main(String[] args) {
    
    
        // 类:是抽象的  需要实例化
        // 类实例化后会返回一个自己的对象
        // student对象就是一个student类的具体实例
        Student xiaoming = new Student();
        Student xh = new Student();
        xiaoming.name="xiaoming";
        xiaoming.age=3;

        System.out.println(xiaoming.name);
        System.out.println(xiaoming.age);

        xh.name="xh";
        xh.age=3;

        System.out.println(xh.name);
        System.out.println(xh.age);
    }
}

类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:

  • 必须和类的名字相同
  • 必须没有返回类型,也不能写void

IDEA:alt+insert 快捷键

构造器:
1、和类名相同
2、没有返回值
作用:
1、使用new关键字,本质是在调用构造器
2、用来初始化对象的值
注意点:
1、定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造


// java --> class
public class Person {
    
    
    String name;

    // 一个类即使什么都不写,也会存在一个方法
    // 显示的定义构造器
    public Person(){
    
    
        //实例化初始值
        // 1、使用new关键字,本质是在调用构造器
        // 2、用来初始化值
        this.name = "123";
    }

    // 有参构造: 一旦定义了有参构造,无参构造就必须显示定义
    public Person(String name){
    
    
        this.name = name;
    }
}

// 一个项目应该只存在一个main方法
public class Application {
    
    
    public static void main(String[] args) {
    
    
        // new实例化了一个对象
        Person person = new Person();
        System.out.println(person.name);//123
    }
}

创建对象内存分析

public class Pet {
    
    

    public  String name;
    public int age;

    public void shout(){
    
    
        System.out.println("叫");
    }
}

public class Application {
    
    
    public static void main(String[] args) {
    
    
        Pet dog = new Pet();
        dog.name="旺财";
        dog.age=3;
        dog.shout();

        System.out.println(dog.name);
        System.out.println(dog.age);
        Pet cat = new Pet();
    }
}

堆:存放new的数组和对象(方法区属于堆)
栈:存放基本变量和引用变量(方法和引用)
在这里插入图片描述

简单小结

1、类与对象

  • 类是一个模板:抽象,对象是一个具体的实例

2、方法

  • 定义、调用

3、对象的引用:

  • 引用类型:基本类型以外的
  • 对象是通过引用来操作的:栈—>堆(地址)

4、属性:字段field 成员变量

  • 属性默认初始化:

    • 数字:0 0.0
    • char:u0000
    • boolean:false
    • 引用:null
  • 修饰符 属性类型 属性名 = 属性值

5、对象的创建和使用

  • 必须使用new关键字创造对象,构造器
  • 对象的属性
  • 对象的方法

6、类:

  • 静态的属性 属性
  • 动态的行为 方法

封装详解

(数据的隐藏—高内聚,低耦合
高内聚: 就是类的内部数据操作细节自己完成,不允许外部干涉
低耦合: 仅暴露少量的方法给外部使用
通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏

属性私有,get/set

// 类  private :私有
public class Student {
    
    

    // 属性私有
    private String name;//姓名
    private int id;// 学号
    private char sex;// 性别
    private int age;

    // 提供一些可以操作这个属性的方法
    // 提供一些public的get set 方法

    // get 获得这个数据
    public String getName(){
    
    
        return this.name;
    }

    // set 给这个数据设置值
    public void setName(String name){
    
    
        this.name = name;
    }

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public char getSex() {
    
    
        return sex;
    }

    public void setSex(char sex) {
    
    
        this.sex = sex;
    }

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        if(age>120 || age<0){
    
     // 不合法
            this.age=3;
        }else{
    
    
            this.age = age;
        }
       
    }
}
// 一个项目应该只存在一个main方法
public class Application {
    
    
    public static void main(String[] args) {
    
    
        Student student = new Student();
        student.setName("123");
        student.getName();
        student.setAge(-1);//不合法
    }
}

封装的意义:

1、提高程序的安全性,保护数据

2、隐藏代码的实现细节

3、统一接口

4、提高系统的可维护性

继承

继承的本质是对某一批类的抽象,,从而实现对现实世界的更好的建模

extends 就是扩展的意思

// person 人 父类
public class Person {
    
    
}

// 学生 is 人  派生类,子类
public class Student extends Person{
    
    
}

// 派生类,子类
public class Teacher extends Person{
    
    
}

继承是类与类之间的一种关系。除此之外,类与类之间的关系还有依赖、组合、聚合等

继承关系的两个类,一个是子类(派生类),一个是父类(基类)。子类继承父类,使用关键字extends来表示。

// person 人  父类
public class Person {
    
    

    private int money = 10_0000_0000;
    public void say(){
    
    
        System.out.println("说话");
    }

    public int getMoney() {
    
    
        return money;
    }

    public void setMoney(int money) {
    
    
        this.money = money;
    }
}

// 学生 is 人  派生类,子类
public class Student extends Person{
    
    
    // 子类继承父类,就会拥有父类的全部方法

}

public class Application {
    
    
    public static void main(String[] args) {
    
    
        Student student = new Student();

        student.say();
        System.out.println(student.getMoney());
    }
}

ctrl+h 可以查看到继承关系

在Java中,所有的类都默认直接或者间接继承object类

java中只有单继承,没有多继承

super详解

注意点:

1、super 调用父类的构造方法,必须在构造方法的第一个

2、super 必须只能出现在子类的方法或构造方法中

3、super 和 this 不能同时调用构造方法

Vs this::

1、代表的对象不同:this(本身调用者这个对象) super(代表父类对象的应用)

2、前提:this(没有继承也可以使用)super(只能在继承条件下才可以使用)

3、构造方法:this()本类的构造;super()父类的构造

// person 人  父类
public class Person /*extends object*/ {
    
    
    protected String name = "111";

    public Person() {
    
    
        System.out.println("Person无参执行了");
    }

    // private 私有的东西无法被继承
    public void print(){
    
    
        System.out.println("Person");
    }
}

// 学生 is 人  派生类,子类
public class Student extends Person {
    
    
    // 子类继承父类,就会拥有父类的全部方法
    private String name = "222";

    public Student() {
    
    
        // 隐藏代码 super():调用了父类的无参构造
        super();// 调用父类的构造器,必须要在子类构造器的第一行
        // this("hello"); // super 和 this 不能同时调用构造方法
        System.out.println("Student无参执行了");
    }

    public Student(String name) {
    
    
        this.name = name;
    }

    public void test(String name) {
    
    
        System.out.println(name);//333
        System.out.println(this.name);//222
        System.out.println(super.name);//111
    }

    public void print() {
    
    
        System.out.println("Student");
    }

    public void test1() {
    
    
        print(); // Student
        this.print();// Student
        super.print();// Person
    }
}

public class Application {
    
    
    public static void main(String[] args) {
    
    
        Student student = new Student();//Person无参执行了  Student无参执行了
//        student.test("333");
//        student.test1();
    }
}

方法的重写

重写:需要有继承关系,子类重写父类的方法

1、方法名必须相同

2、参数列表必须相同

3、修饰符:范围可以扩大,但不能缩小。 public>protected>default>private

4、抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException --> Exception(大)

重写,子类的方法和父类必须要一致,方法体不同!

为什么需要重写?

1、父类的功能子类不一定需要,或者不一定满足!

// 重写都是方法的重写,和属性无关
public class B {
    
    

//    public static void test(){
    
    
//        System.out.println("B-Test()");
//    }

    public  void test(){
    
    
        System.out.println("B-Test()");
    }
}

// 继承
public class A extends B{
    
    

 //   public static void test(){
    
    
//        System.out.println("A-Test()");
//    }

//    public  void test(){
    
    
//        System.out.println("A-Test()");
//    }

    // 重写
    @Override
    public void test() {
    
    
        System.out.println("A-Test()");
    }
}

public class Application {
    
    

    // 静态方法和非静态的方法区别很大
    // 静态方法 // 方法的调用,只和(左边)定义的数据有关
    // 非静态方法 (重写) // 子类重写了父类的方法(重写只与非静态方法有关)
    public static void main(String[] args) {
    
    

        A a = new A();
        a.test();// A

        // 父类的引用指向了子类
        B b =new A();
        b.test();// B  A(重写后)
    }
}

多态

动态编译:类型:可扩展性

即同一个方法可以根据发送对象的不同而采用多种不同的行为方式

一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(父类,有关系的类)

多态注意事项:

1、多态是方法的多态,属性没有多态

2、父类和子类,有联系 (类型转换异常)ClassCastException

3、多态存在的条件:继承关系,方法需要重写,父类的引用指向子类对象 father f1 = new Son();

不能被重写的方法:
1、static 方法,属于类,不属于实例
2、final 常量
3、private 方法(私有)

public class Person {
    
    

    public void run(){
    
    
        System.out.println("run");
    }
}

public class Student extends Person{
    
    
    @Override
    public void run() {
    
    
        System.out.println("son");
    }

    public void eat(){
    
    
        System.out.println("eat");
    }
}

public class Application {
    
    

    public static void main(String[] args) {
    
    

        // 一个对象的实际类型是确定的
        //  new Student()

        // 可以指向的引用类型就不确定了:父类的引用指向子类

        // Student 能调用的方法都是自己的或者继承父类的
        Student s1 = new Student();
        // 父类的引用指向子类:person 父类,可以指向子类 但是不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();

        // 对象能执行哪些方法主要看对象左边的类型,和右边关系不大
        s2.run();// son 子类重写了父类的方法,执行子类的方法
        s1.run();// son

        // ((Student)s2).eat();

    }
}

instanceof和类型转换

instanceof (类型转换) 引用类型,判断一个对象时什么类型

public class Person {
    
    

    public void run(){
    
    
        System.out.println("run");
    }
}

public class Teacher extends Person{
    
    

}

public class Student2 extends Person{
    
    

}

public class Application {
    
    

    public static void main(String[] args) {
    
    

        // object> person> student
        // object> person> teacher
        // object> string
        Object object = new Student2();

        // System.out.println(x instanceof y);// 能不能编译通过

        System.out.println(object instanceof Student2);// true
        System.out.println(object instanceof Person);// true
        System.out.println(object instanceof Object);// true
        System.out.println(object instanceof Teacher);// false
        System.out.println(object instanceof String);//false

        Person person = new Student2();
        System.out.println(person instanceof Student2);// true
        System.out.println(person instanceof Person);// true
        System.out.println(person instanceof Object);// true
        System.out.println(person instanceof Teacher);// false
        // System.out.println(person instanceof String);//编译报错

        Student2 student = new Student2();
        System.out.println(student instanceof Student2);// true
        System.out.println(student instanceof Person);// true
        System.out.println(student instanceof Object);// true
        // System.out.println(student instanceof Teacher);// 编译报错
        // System.out.println(student instanceof String);// 编译报错
    }
}

多态
1、父类引用指向子类对象
2、把子类转换为父类,向上转型,自动转换
3、把父类转换为子类,向下转型,强制转换,可能会丢失自己的方法
4、方便方法的调用,减少重复的代码,简洁代码

public class Person {
    
    

    public void run(){
    
    
        System.out.println("run");
    }
}

public class Student2 extends Person{
    
    
    public void go(){
    
    
        System.out.println("go");
    }
}

public class Application {
    
    

    public static void main(String[] args) {
    
    
        // 类型之间的转换:父类 子类

        // 高                    低
        Person obj = new Student2();

        // student 将这个对象转换为Student类型,我们就可以使用Student类型的方法了

        Student2 s = (Student2) obj;
        s.go();
        ((Student2) obj).go();

        // 子类转换为父类,可能会丢失自己的本来一些方法
        Student2 student2 = new Student2();
        Person person = student2;
    }
}

static 关键字详解

// static
public class Student {
    
    
    private static int age;//静态变量
    private  double score; // 非静态变量

    public void run(){
    
    
        go();
    }

    public static void go(){
    
    

    }

    public static void main(String[] args) {
    
    
        Student s1 = new Student();
        go();
        System.out.println(Student.age);
        System.out.println(s1.age);
        System.out.println(s1.score);
    }
}
public class Person {
    
    

    // 2:赋初始值~
    {
    
    
        // 代码块(匿名代码块) 在构造器之前
        System.out.println("匿名代码块");
    }

    // 1:只执行一次~
    static {
    
    
        // 静态代码块
        System.out.println("静态代码块");
    }

    // 3
    public Person() {
    
    
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
    
    
        Person person1 = new Person();//静态代码块  匿名代码块  构造方法
        System.out.println("=================");
        Person person2 = new Person();// 匿名代码块  构造方法
    }
}

package com.oop.demo07;

//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        System.out.println(random());
        System.out.println(PI);
    }
}

  • 被final修饰的不能被继承(final之后断子绝孙)

抽象类

abstract 修饰符可以用雷修饰方法也可以修饰类,抽象方法和抽象类。

抽象类的特点:
1、不能new 这个抽象类,只能靠子类去实现它:约束
2、抽象类中可以写普通方法
3、抽象方法必须在抽象类中,抽象方法只有方法的声明,没有方法的是实现,它是用来让子类实现的
4、抽象类存在默认构造器
5、抽象类抽象出来,目的是为了提高开发效率
抽象的抽象:约束

// abstract抽象类 :类 extends (单继承)
public abstract class Action {
    
    

    //约束  有人帮我们实现
    // abstract , 抽象方法,只有方法名字,没有方法的实现
    public abstract void doSomething();

    public void hello(){
    
    
        
    }
}


public class A extends Action{
    
    
    // 抽象类的所有方法,继承他了的子类,都必须实现它的方法 ,除非A也是abstract
    @Override
    public void doSomething() {
    
    

    }
}

接口的定义与实现

普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有!
接口:只有规范!自己无法写方法,专业的约束!约束和实现分离:面向接口编程

接口的本质是契约,声明接口的关键字是interface

// 抽象的思维
// interface 定义的关键字,接口都需要有实现类
public interface UserService {
    
    

    // 常量 public static final
    int AGE =99 ;

    // 接口中的所有定义其实都是抽象的 public abstract
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}

public interface TimeService {
    
    
    void timer();
}

// 类 可以实现接口 implements 接口
// 实现了接口的类,就需要重写接口中的方法
// 多几次  利用接口实现多继承~
public class UserServiceImpl implements UserService,TimeService{
    
    
    @Override
    public void add(String name) {
    
    

    }

    @Override
    public void delete(String name) {
    
    

    }

    @Override
    public void update(String name) {
    
    

    }

    @Override
    public void query(String name) {
    
    

    }

    @Override
    public void timer() {
    
    

    }
}

接口的作用:
1、约束
2、定义一些方法,让不同的人实现
3、public abstract
4、public static final
5、接口不能被实例化,接口中没有构造方法
6、implements 可以实现多个接口
7、必须要重写接口中的方法

N种内部类

内部类就是在一个类的内部在定义一个类。

成员内部类

public class Outer {
    
    

    private int id = 10;

    public void out() {
    
    
        System.out.println("这时外部类的方法");
    }

    public class Inner {
    
    
        public void in() {
    
    
            System.out.println("这时内部类的方法");
        }

        // 内部类可以访问外部类的一些私有变量
        // 获得外部类的私有属性 私有方法
        public void getId() {
    
    
            System.out.println(id);
        }
    }
}

public class Application {
    
    

    public static void main(String[] args) {
    
    
        Outer outer = new Outer();
        // 通过外部类来实例化内部类
        Outer.Inner inner =outer.new Inner();
        inner.in();
        inner.getId();
    }
}

静态内部类

public class Outer {
    
    

    private int id = 10;

    public void out() {
    
    
        System.out.println("这时外部类的方法");
    }

    public static class Inner {
    
    
        public void in() {
    
    
            System.out.println("这时内部类的方法");
        }
    }
}

局部内部类

public class Outer2 {
    
    

    // 局部内部类
    public void method(){
    
    
        class Inner{
    
    
            public  void in(){
    
    

            }
        }
    }
}

匿名内部类

public class Test {
    
    
    public static void main(String[] args) {
    
    
        // 没有名字初始化类,不用将实例保存在变量中
        new Apple().eat();
        // 匿名内部类
        UserService userService= new UserService(){
    
    

            @Override
            public void hello() {
    
    

            }
        };
    }
}

class Apple{
    
    
    public void  eat(){
    
    
        System.out.println("1");
    }
}

interface UserService{
    
    
    void hello();
}

异常机制

异常指程序运行中出现的不期而至的各种情况,如:文件找不到,网络连接失败。异常发生在程序运行期间,它影响了正常的程序执行流程。

public class Demo01 {
    
    
    public static void main(String[] args) {
    
    
        System.out.println(11/0);
    }
}

简单分类

  • 检查性异常:用户错误或问题引起的异常,这时程序员无法预见的。(例如打开一个不存在的文件),这些异常在编译的时候不能被简单的忽略
  • 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  • 错误error:错误不是异常,而是脱离程序员控制的问题,错误在代码中通常被忽略。(例如:当栈溢出时,一个错误就发生了,)在编译也检查不到的

Error和Exception

异常体系结构
在这里插入图片描述

error

error是由Java虚拟机生成并抛出的,大多数错误与代码编写者执行的操作无关。

Java虚拟机运行错误(Virtual MachineError),当jvm不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError(内存溢出)。这些异常发生时,Java虚拟机一般会选择线程终止。

还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为他们在应用程序的控制和处理能力之外,二千绝大多数是程序运行时不允许出现的状况。

Exception

在Exception分支中有一个重要的子类RuntimeException(运行时异常)

  • ArrayIndexOutOfBoundsException(数组下标越界)
  • NullPointerException(空指针异常)
  • ArithmeticException(算术异常)
  • MissingResourceException(丢失资源)
  • ClassNotFoundException(找不到类)
    这些异常不是检查异常,程序中可以选择捕获处理,也可以不处理

这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生

Error和Exception的区别

error通常灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机一般会选择终止线程;

Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常

捕获和抛出异常

try 、catch、finally、throw、throws

public class Test {
    
    
    public static void main(String[] args) {
    
    
        int a =1;
        int b =0;

        // 假设要捕获多个异常:从小到大捕获

        try{
    
    // try 监控区域
            System.out.println(a/b);
        }catch (ArithmeticException e){
    
     // catch(想要捕获的异常类型) 捕获异常
            System.out.println("程序出现异常,变量b不能为0");
        }catch (Exception e){
    
    
            System.out.println("Exception");
        }catch (Throwable t){
    
    
            System.out.println("Throwable");
        }finally {
    
     // 处理善后工作
            System.out.println("finally");
        }
        // finally 可以不要,假设IO,资源,关闭

        try{
    
    // try 监控区域
            new Test().a();
        }catch (Throwable e){
    
     // catch(想要捕获的异常类型) 捕获异常
            System.out.println("程序出现异常,变量b不能为0");
        }
    }

    public void a(){
    
    
        b();
    }

    public void b(){
    
    
        a();
    }
}

IDEA 快捷键 ctrl +alt +t

public class Test2 {
    
    
    public static void main(String[] args) {
    
    
        int a =1;
        int b =0;

        try{
    
    
            System.out.println(a/b);
        }catch (Exception e){
    
    
            e.printStackTrace();// 打印错误的栈信息
        }
       
    }
}
public class Test2 {
    
    
    public static void main(String[] args) {
    
    
        try{
    
    
            new Test2().test(1,0);
        }catch (ArithmeticException e){
    
    
            e.printStackTrace();
        }
    }

    // 假设这方法中,处理不了这个异常,方法上抛出异常
    public void test(int a , int b) throws ArithmeticException{
    
    
        if(b==0){
    
    // 主动抛出异常  throw  throws
            throw new ArithmeticException();// 主动抛出异常,一般在方法中使用
        }
    }
}

自定义异常

用户自定义异常类,只需要继承Exception类即可。

在程序中自定义异常类,可以有已下几个步骤:
1、创建自定义异常类
2、在方法中通过throw关键字抛出异常对象3、如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
4、在出现异常方法的调用者中捕获并处理异常

// 自定义异常类
public class MyException extends Exception{
    
    

    // 传递数字 >10
    private  int detail;

    public MyException(int a) {
    
    
        this.detail = a;
    }

    // toString:异常的额打印信息
    @Override
    public String toString() {
    
    
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}

public class Test {
    
    

    // 可能会存在异常的方法
    static void test(int a) throws MyException{
    
    
        System.out.println("传递的参数:"+a);
        if (a>10){
    
    
            throw new MyException(a); // 抛出
        }
        System.out.println("ok");
    }

    public static void main(String[] args) {
    
    
        try {
    
    
            test(11);
        }catch (MyException e){
    
    
 // 增加一些处理异常的代码块            
 System.out.println("MyException=>"+e);//MyException=>MyException{11}
        }
    }
}

实际应用中的经验总结

1、处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
2、在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
3、对于不确定的代码,也可以加上try-catch,处理潜在的异常(IDEA Alt+enter)
4、尽量去处理异常,切记只是简单的调用printStackTrace()去打印输出
5、具体如何处理异常,要根据不同的业务需求和异常类型去决定
6、尽量添加finally语句块去释放占用的资源

【狂神说Java】Java零基础学习视频通俗易懂https://www.bilibili.com/video/BV12J41137hu

猜你喜欢

转载自blog.csdn.net/fggsgnhz/article/details/115187051
今日推荐