Java学习笔记(基础)

  • JDK = JRE + 开发工具类(例如Javac,java编译工具等)
  • JRE = JVM + Java SE标准类库(java核心类库)

常见问题及解决办法

一、文件中有中文时,编译出现乱码或无反应

  • File —> Save with Encoding
  • javac -encoding utf-8 待编译文件名

+++

二、NoSuchElementException

集合 迭代次数 过多

Scanner 未开启

+++

三、ConcurrentModificationException

迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致

Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();	//并发修改异常
    if(s.equals("world")) {
        list.add("javaee");
    }
}

开发细节

  • 源文件(只能有一个public类)编译后,每一个类,都会生成一个对应的class文件
  • 当我们对运算结果是小数,来进行判断时,要小心,因使用差值在某个精度范围来判断

文档注释

基本格式

/**
	*@author yang
	*@version 1.0
*/

如何生成对应的文档注释

javadoc -d 文件夹名(路径) xx -yy 待生成源文件名

例子:javadoc -d D:\\Java\code\temp -author -version Hello.java

IDEA常用快捷键

快捷键 作用
Ctrl + Y 删除当前行
Ctrl + D 复制当前行
Alt + / 补全代码
Alt + Enter 自动导包,自动分配变量名
Ctrl + Shift + L 格式化代码
Alt + R 快速运行代码
Alt + Insert 生成构造方法
Ctrl + H 查看层级关系
Ctrl + 点击 定位方法

DOS命令

dos命令 作用
dir 查看当前目录
cd 切换盘符
cd .. 返回上一级
cd \ 切换到根目录
tree 查看所有的子目录
cls 清屏
exit 退出DOS
md 创建目录
rd 删除目录
copy 删除目录拷贝文件
cd> 创建文件
del 删除文件
echo 输入内容到文件
type 输入内容到文件
move 剪切文件
calc 计算机
mspaint 画图软件
notepad 记事本

数据结构

一、基本数据类型

1.整数类型

数据类型 占用内存 取值范围
byte 1个字节 -128~127
short 2个字节 -3_2768~3_2767
int 4个字节 -21_4748_3648~21_4748_3647
long 8个字节 -922_3372_0368_5477_5808~-922_3372_0368_5477_5807
        //整数类型
        byte num1 = 100;
        int num2 = 20;		//默认为int类型
        short num3 = 30;
        long num4 = 40L;    //long类型要在数值后加 “L”

2.浮点类型

数据类型 占用内存 有效数字位数
float 4个字节 8位
double 8个字节 16位
        //浮点类型
        float num5 = 40.5F;		//float类型要在数值后加 “F”
        double num6 = 3.14159;	//默认为double类型

注意:尽量不要使用浮点数来比较大小

​ 也不要使用计算结果为浮点数的值,来进行比较

​ 而应用差值精度比较

        float f = 0.4F;
        double d = 0.4;

        System.out.println(f>d);    //true

3.字符类型

  • char——占2个字节

            //字符型
            char c1 = '\n'; //换行
            char c2 = '\b'; //退格
            char c3 = '\t'; //水平制表
            char c4 = '\''; //单引号
            char c5 = '\"'; //双引号
            char c6 = '\\'; //反斜线
    

4.逻辑类型

  • boolean——占1个位

      		//布尔类型
            boolean flag1 = true;
            boolean flag2 = false;
    

二、类型转换

1.精度排序

低----------------------高

byte,short,char —> int —> long —> flaot —>double

2.转换原则

低——>高 自动装换

高——>低 强制转换

3.注意事项

  • byte,short,char之间的运算,计算时首先转换为int类型

3.2精度丢失

从小数转换成整数的时候,会丢失小数部分

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

3.4数据溢出

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

        int i = 128;        byte b = (byte)i;        System.out.println(b);  //-128

三、引用数据类型

1.类

2.接口

3.数组

运算符

进制

进制:二进制(0b) 八进制(0) 十六进制(0x)

        int i1 = 10;    //10        int i2 = 010;   //8        int i3 = 0x10;  //16

一、算术运算符

  • 加减乘除运算符

不同类型的数据进行运算时,

若数据中有Long型,则结果为Long型

否则,结果为Int型

        int a = 10;        int b = 25;        System.out.println(a+b);    //35        System.out.println(a-b);    //-15        System.out.println(a*b);    //250        System.out.println(a/b);    //0        System.out.println(a/(float)b);    //0.4

  • 求模运算符
    	//模运算		int a = 10;        int c = 22;        System.out.println(c%a);    //2		//a % b 本质: a - a / b * b		//结果只取决 a的符号		System.out.println(-10 % 3);//-1		System.out.println(10 % -3);//1

二、自增、自减运算符

++ --

		int i = 1;		i= i++;		//(1)temp=i (2)i=i+1 (3)i=temp		System.out.println("i = " + i);	//1		int j = 1;		j = ++j;	//(1)i=i+1 (2)temp=i (3)i=temp		System.out.println("j = " + j);	//2		//会自动进行类型转换		byte b = 3;		b++;	//b = (byte)(b + 1);

三、关系运算符

关系运算符返回的结果:false or true(布尔类型)

		int a = 10;        int b = 20;        int c = 22;        System.out.println(a>b);	//false        System.out.println(a<b);	//true        System.out.println(a==b);	//false        System.out.println(a!=b);	//true

四、逻辑运算符

&&(与) 一假则假

|| (或) 一真则真

! (非) 取反

       	//短路逻辑运算符		boolean a = true;        boolean b = false;        System.out.println(a&&b);   //false        System.out.println(a||b);   //true        System.out.println(!(a&&b); //true

五、位运算符

& | ^ ~

          A = 0011 1100          B = 0000 1101        ---------------        A&B = 0000 1100        A|B = 0011 1101        A^B = 0011 0001        ~B  = 1111 0010

<< >>

        //	<<  *2        //	>>  /2        System.out.println(2<<3);	//16

六、instanceof运算符(略)

左边的操作元是一个对象,右边的操作元是一个类

当左边的对象是右边的类或是子类创建的对象是,结果为true,否则为false

七、三目运算符

? :

        // x ? y : z;        //若x成立,则执行y,否则执行z		//y z 只能是表达式,不能是语句        int score = 90;        String type = score < 60 ? "不及格" : "及格";        System.out.println(type);	//及格

八、扩展赋值运算符

+= -+ *= /=

		//复合赋值运算符会进行类型转换		byte b = 3;		b += 2;//等价于 b = (byte)(b + 2)

流程控制

一、选择结构

  • if选择结构
        if(score > 90 && score <= 100){            System.out.println("A级");        }else if(score > 80 && score <= 90){            System.out.println("B级");        }else if(score > 70 && score <= 80){            System.out.println("C级");        }else if(score >= 60 && score <= 70){            System.out.println("D级");        }else if(score >= 0 && score < 60){            System.out.println("不及格");        }else{            System.out.println("成绩不合法");        }
  • swtich选择结构

switch语句中表达式的值不可以是long,double,flaot型的数据

        switch(s){            case "A":                System.out.println("优秀");                break;            case "B":                System.out.println("良好");                break;            case "C":                System.out.println("及格");                break;            case "D":                System.out.println("挂科");                break;            default:                System.out.println("未知等级");        }

二、循环结构

1.while循环

       	//输出1~10 		int i = 0;        while(i<10){            i++;            System.out.println(i);        }

2.do...while循环

        //输出1~10 		int i = 0;        do{            i++;        }while (i<10);        System.out.println(i);

3.for循环

		//输出1~10		for (int i = 0; i < 10; i++){            i++;            System.out.println("i")        }

四、break,continue语句

break: 结束循环体

continue: 结束本次循环,进行下次循环

面向对象

一、基本介绍

1.类和对象的关系

  1. 类是一种数据结构,是抽象的
  2. 对象是一个具体的实例
  3. 类是对象的模板;对象是类的一个个体

2.对象在内存中存在形式

  1. 栈: 一般存放基本数据类型(局部变量)
  2. 堆: 存放对象(Cat cat , 数组等)
  3. 方法区:常量池(常量,比如字符串), 类加载信息

image-20211010113352932

二、类成员

1.属性

  1. 类的一个组成部分,可以是基本数据类型,也可以使引用类型

  2. 定义语法: 访问修饰符 属性类型 属性名

  3. 属性存在默认值,规则和数组一致:

    ​ byte, short, int, long--0 float, double--0.0 char--\u0000 boolean--false


2.成员方法

  1. 定义语法:访问修饰符 返回值类型 方法名称(形参列表)

  2. 好处:

    ​ 提高代码的复用性

    ​ 可以将实现的细节封装起来,然后供其他用户来调用即可

3.构造器

  1. 基本语法:修饰符 方法名(形参列表)

  2. 构造器可以重载

  3. 构造器是完成对象的初始化,并不是创建了对象

  4. 注意点:

    ​ a. 定义了自己的构造器,默认构造器就会被覆盖

    ​ b. 构造器没有返回值

    ​ c. 方法名和类名必须一样

    ​ d. 构造器的调用,由系统完成

4.类成员

  1. 类成员也叫静态变量/静态属性。同一个类的所有对象共享,并且在类加载时就生成了
  2. 定义语法:访问修饰符 static 数据类型 变量名;
  3. 访问方式:类名.类变量名

5.类方法

三、方法重载

1.基本介绍

  1. Java中允许同一个类,多个同名方法的存在,但要求 形参列表 不一致

  2. 好处:

    ​ 减轻了起名的麻烦

    ​ 减轻了记名的麻烦

2.重载条件

  1. 方法名:必须相同
  2. 形参列表:必须不同【形参类型、个数或顺序,至少一个不同】
  3. 返回值类型:无要求

四、作用域

  1. 属性和局部变量可以重名,访问时遵循就近原则
  2. 在同一个作用域中,两个变量名不可以重名

五、this关键字

  1. this关键字可以用来访问本类的属性、方法、构造器
  2. this用于区分当前类的属性和局部变量
  3. 访问成员方法语法:this.方法名(参数列表)
  4. 访问构造器语法:this(参数列表)【只能在构造器中使用,且必须是第一条语句】

六、底层原理

1.Java创建对象的流程

  1. 先进行类加载(加载class文件,只会加载一次)

  2. 在堆中分配空间

  3. 完成对象初始化

    ​ 【1.默认初始化 2.显式初始化 3.构造器初始化】

  4. 把地址返回,对象就成功实例化


2.方法的调用机制原理

  1. 当程序执行到方法时,就会开辟一个独立的栈空间
  2. 当方法执行完毕,或者执行到return语句时,就会返回到调用方法的地方
  3. 返回后,继续执行方法后面的代码
  4. 当main方法执行完毕后,整个程序退出

3.传参机制

  1. 基本数据类型,传递的是值,即值拷贝【形参无法改变实参】
  2. 引用数据类型,传递的是地址【形参可以改变实参】

七、包

1.好处

  1. 区分相同名字的类
  2. 当类很多时,可以很好的管理类
  3. 控制访问范围

2.包的命名

  1. 命名规则:只能包含数字、字母、下划线、小圆点,但不能用数字开头,不能是关键字
  2. 命名规范:com.公司名.项目名.业务模块名

3.导包

语法:import 包;

八、访问修饰符

访问修饰符 本类 同包 子类 本类
public
protected
默认
private

九、封装

1.基本介绍

  1. 封装就是把属性和方法封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作,才能对数据进行操作
  2. 好处:可以对数据进行验证,保证安全合理

2.实现步骤

  1. 将属性进行私有化
  2. 提供一个public修饰的set方法,用于对属性判断并赋值
  3. 提供一个public修饰的get方法,用于获取属性的值

十、继承

1.基本介绍

  1. 基本语法:class 子类 extends 父类
  2. 父类又叫 超类,基类
  3. 子类又叫 派生类
  4. 好处:提高代码的复用性,扩展性和维护性

2.使用细节

  1. 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
  2. 子类必须调用父类的构造器, 完成父类的初始化 【默认隐式调用】
  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器。如果父类没有提供无 参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则不会通过编译
  4. super 在使用时,必须放在构造器第一行【super 只能在构造器中使用】
  5. super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
  6. java 所有类都是 Object 类的子类, Object 是所有类的基类
  7. 父类构造器的调用不限于直接父类。将一直往上追溯直到 Object 类(顶级父类)
  8. 子类最多只能继承一个父类【单继承机制】
  9. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

3.继承的本质

当子类对象创建好后,建立查找的关系

查找属性或方法:自子类开始查找,找到则返回,未找到则继续找上级父类,直至Object

image-20211010203846247


4.super关键字

  1. super 代表父类的引用,用于访问父类的属性、方法和构造器

  2. 基本语法:

    ​ a. 访问父类的属性,但不能访问父类的private属性【super.属性名】

    ​ b. 访问父类的方法,但不能访问父类的private方法【super.方法名(参数列表)】

    ​ c. 访问父类的构造器【super(参数列表)】

区别点 this super
访问属性 访问本类中的属性。如果没有,则从父类中继续查找 从父类中开始查找属性
调用方法 访问本类中的属性。如果没有,则从父类中继续查找 从父类中开始查找方法
调用构造器 调用本类构造器,必须放在构造器的首行 调用父类构造器,必须放在构造器的首行
特殊 表示当前对象 子类中访问父类对象

5.方法重写

  1. 子类的一个方法和父类的某个方法的名称、返回类型、参数一样,即子类重写了父类的方法
  2. 子类方法的返回值可以是父类方法返回值的子类,不一定要一样
  3. 子类方法不可以缩小父类方法的访问权限
名称 发生范围 方法名 形参列表 返回类型 修饰符
重载(overload) 本类 必须一样 类型,个数或者顺序至少有一个不同 无要求 无要求
重写(override) 父子类 必须一样 相同 子类重写的方法,返回的类型和父类返回的类型一致,或者是其子类 子类方法不能缩小父类方法的访问范围

十一、多态

1.基本介绍

  1. 方法或对象具有多种形态。多态是建立在封装和继承的基础上的
  2. 多态的前提:两个对象或类 存在继承关系

2.多态的具体体现

  1. 方法重载,方法重写体现多态
  2. 对象的多态【重点】
  3. 多态数组
  4. 多态参数

3.对象的多态

3.1基本介绍

  1. 一个对象的编译类型和运行类型可以不一致
  2. 编译类型在定义对象时,就确定了,不能改变
  3. 运行类型是可以改变的
  4. 编译(类型)看左边,运行(类型)看右边

3.2向上转型

  1. 本质:父类的引用指向了子类对象

  2. 语法:父类类型 引用名 = new 子类类型();

  3. 特点:可以调用父类中的所有成员【需遵循访问权限】

    ​ 不能调用子类中特有成员【因为在编译阶段,能调用哪些成员,是由编译类型来决定的】

    ​ 最终运行效果看子类的具体实现【动态绑定】

3.3向下转型

  1. 语法:子类类型 引用名 = (子类类型) 父类类型
  2. 特点:只能强转父类的引用,不能强转父类的对象

3.4使用细节

  1. 属性没有重写之说。属性的值看编译类型

  2. instanceof :比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类

  3. Java的动态绑定机制:当调用对象方法的时候,该方法会和该对象的运行类型绑定

    ​ 当调用对象属性时,没有动态绑定机制。哪里声明,哪里使用

Object类详解

一、equals方法

1.== 和 equals 的对比

  1. == 是一个比较运算符
  2. == 既可以判断基本类型(判断值是否相等),又可以判断引用类型(判断地址是否相等)
  3. equals:是Object类中的方法,只能判断引用类型
  4. 默认判断的是地址是否相等。子类中往往重写了该方法,用于判断内容是否相等

2.重写equals方法示例

//判断两个 Person 对象的内容是否相等, class Person{      private String name;     private int age;     //重写 Object 的 equals 方法     public boolean equals(Object obj) {            	//判断如果比较的两个对象是同一个对象,则直接返回 true         if(this == obj)  {             return true;         }            	//类型判断         if(obj instanceof Person) {        //是 Person,我们才比较          //进行 向下转型, 因为我需要得到 obj 的 各个属性             Person p = (Person)obj;             return this.name.equals(p.name) && this.age == p.age;         }     //如果不是 Person ,则直接返回 false         return false;     }

二、hashCode方法

  1. 返回该对象的哈希值,提高具有哈希结构的容器的效率
  2. 两个引用,如果指向的是同一对象,则哈希值肯定是一样的
  3. 两个引用,如果指向的是不同对象,则哈希值肯定是不一样的
  4. 哈希值是根据地址号来转化而成的,不能完全将哈希值等价于地址

三、toString方法

  1. 默认返回:全类名+@+哈希值的十六进制
  2. 子类往往重写toString方法,用于返回对象的属性信息

数组

一、数组声明

        //静态创建:声明 + 创建        int[] array = {1,2,3,4,5};        //动态创建:默认初识值为0        int[] array = new int[10];

二、数组使用

1.遍历数组

        //For循环遍历        for (int i = 0; i < array.length; i++){            System.out.print(array[i] + "\t");        }		//Array类遍历		for (int i : array) {            System.out.print(i + "\t");        }

2.反转数组

    public static int[] reverse(int[] array){        int[] reverse = new int[array.length];        //实现反转        for (int i = 0; i < array.length; i++){            reverse[i] = array[array.length - 1 - i];        }                return reverse;    }

三、二维数组

  • 一个二维数组是由若干个一维数组构成的

  • 构成二维数组的一维数组不必有相同的长度

  • 常见错误:ArrayIndexOutOfBoundsExceprion(数组下标越界)

        //创建二位数组		int[][] array = {{1}, {2,3},{4,5,6}};		//查看二位数组长度        System.out.println(array.length);   //3,一维数组的个数        System.out.println(array[0].length);//1,一维数组的元素个数        System.out.println(array[1].length);//2,同上        System.out.println(array[2].length);//3,同上        //遍历二维数组		//For循环遍历        for (int i = 0; i < array.length; i++) {            for (int j = 0; j < array[i].length; j++) {                System.out.print(array[i][j] + "\t");            }            System.out.println();        }		//Array类遍历        for (int[] ints : array) {            for (int anInt : ints) {                System.out.print(anInt + "\t");            }            System.out.println();        }

四、数组的引用

        int[] a = {5,69,87,1,69};        int[] b = {84,26,32};		//前提:两个数组的类型必须相同        a = b;	//a引用了 b所引用的数组		/*		结果:            a = {84,26,32};            b = {84,26,32};		*/

五、扩展内容

1.Arrays类的使用

		int[] a = {58,69,256,3,488,62,78};       		//数组打印:Arrays.toString(int [] a)        System.out.println(Arrays.toString(a));		//[58, 69, 256, 3, 488, 62, 78]        //数组排序:Arrays.sort(int [] a)        Arrays.sort(a);		//[3, 58, 62, 69, 78, 256, 488]        //数组填充	[fromlndex, tolndex)		//Arrays.fill(int [] a, (fromlndex), (tolndex), val);        Arrays.fill(a, 2, 4, 0);		//[3, 58, 0, 0, 78, 256, 488]

2.char型数组

        char[] a = {'五','邑','大','学'};        System.out.println(a);  //五邑大学        System.out.println(""+a);   //输出char型数组的引用

3.冒泡排序

		public static int[] sort1(int[] array){            for (int i = 0; i < array.length; i++) {                for (int j = 0; j < array.length-1-i; j++) {                    if (array[j] > array[j+1]){                        int temp = array[j];                        array[j] = array[j+1];                        array[j+1] = temp;                    }                }            }            return array;        }

4.稀疏数组

  • 原始数组:(11 * 11)

    0 0 0 0 0 0 0 0 0 0 0
    0 0 1 0 0 0 0 0 0 0 0
    0 0 0 2 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0

原始数组 转换成 稀疏数组

    //转换成稀疏数组        //1、获取有效数字个数        int sum = 0;        for (int[] ints : array1) {            for (int anInt : ints) {                if (anInt != 0){                    sum++;                }            }        }        //2、创建稀疏数组        int[][] array2= new int[sum+1][3];        array2[0][0] = 11;        array2[0][1] = 11;        array2[0][2] = sum;        //3、将非零的值,存放在稀疏数组中        int count = 0;        for (int i = 0; i <array1.length; i++) {            for (int j = 0; j < array1[i].length; j++) {                if (array1[i][j] != 0){                    count++;                    array2[count][0] = i;                    array2[count][1] = j;                    array2[count][2] = array1[i][j];                }            }        }        ///4、打印稀疏数组        System.out.println("稀疏数组为:");        for (int[] ints : array2) {            for (int anInt : ints) {                System.out.print(anInt + "\t");            }            System.out.println();        }

稀疏数组 转化成 原始数组

    //稀疏数组还原        //1、创建还原数组        int[][] array3 = new int[array2[0][0]][array2[0][1]];        //2、数组赋值        for (int i = 1; i < array2[0][2]+1; i++) {            array3[array2[i][0]][array2[i][1]] = array2[i][2];        }        //3、打印还原数组        System.out.println("还原数组为:");        for (int[] ints : array3) {            for (int anInt : ints) {                System.out.print(anInt + "\t");            }            System.out.println();        }

设计模式

一、单例模式

1.饿汉式

a.步骤

  1. 构造器私有化——防止直接 new
  2. 类内部直接创建对象
  3. 向外提供一个静态的公共方法

b.代码实例

public class SingleTone01 {        //构造器私有化——防止直接 new    public SingleTone01() {}        //类内部直接创建对象    private static SingleTone01 instance = new SingleTone01();    //向外提供一个静态的公共方法    public static SingleTone01 getInstance() {        return instance;    }}

+++

2.懒汉式

a.步骤

  1. 构造器私有化——防止直接 new
  2. 提供一个静态属性
  3. 向外提供一个静态的公共方法

b.代码实例

public class SingleTone02 {    //构造器私有化——防止直接new    private SingleTone02() { }    //提供一个静态属性    private static SingleTone02 instance;    //提供一个public的静态方法    public static SingleTone02 getInstance() {        if (instance == null) {            instance = new SingleTone02();        }        return instance;    }}

+++

3.饿汉式VS懒汉式

  1. 创建对象的时机不同:前者是在类加载时,后者是在使用时
  2. 饿汉式存在浪费资源的可能性
  3. 懒汉式存在线程安全

final关键字

一、使用场景

  1. 不希望被继承
  2. 不希望父类的某个方法被子类覆盖/重写
  3. 不希望类的某个属性的值被修改
  4. 不希望某个局部变量别修改

+++

二、使用细节

  1. final修饰的属性又叫常量,一般用 XX_XX_XX 命名

  2. final修饰的属性在定义时,必须赋初值,并且不能再修改

    赋值位置:a.定义时;b.构造器中;c.代码块中

  3. 如果final修饰的属性是静态的,则不能在构造器中初始化

  4. final类不能继承,但可以实例化

  5. final不能修饰构造方法

  6. final 和 static 往往搭配使用,有奇效!!!

    补充:被这两个修饰符同时修饰的变量,被调用时不会使得类加载

抽象类

一、使用场景

当父类的一些方法不能确定时,可以用 abstract 关键字来修饰该方法

抽象规则:相同代码提取,不同代码抽象

+++

二、使用细节

  1. 抽象类可以有任意成员【因为抽象类还是类】
  2. 抽象方法不能使用 private、final和static 来修饰【因为这些关键字都是和重写相违背的】

接口

一、使用场景

接口就是给出一些没有实现的方法,封装到一起,到某个类要使用时,再根据具体情况把这些方法写出来

+++

二、使用细节

  1. 接口不能实例化
  2. 接口中的方法,默认修饰符为:public、abstract
  3. 接口中的属性,默认修饰符为:public、statci、final
  4. 一个普通类实现接口,就必须将该接口的所有方法都实现
  5. 抽象类实现接口,可以不用实现接口的方法
  6. 一个类可以实现多个接口
  7. 一个接口不能继承其他的类,但是可以继承多个接口
  8. 接口的修饰符只能是:public、默认

+++

三、接口 VS 继承

  1. 接口解决代码的延展性,继承解决代码的复用性
  2. 实现接口,是对Java单继承的补充
  3. 接口在一定程度上实现代码解耦【即:接口规范性+动态绑定】

+++

四、多态特征

多态参数 多态数组 多态传递

内部类

一、局部内部类(有类名)

1.基本介绍

定义位置:方法中、代码块中

2.使用细节

  1. 相当于一个 局部变量,不能使用修饰符修饰【final除外】

  2. 作用域:仅仅在定义它的方法或代码块中

  3. 局部内部类 可以直接访问 外部类的成员 (如何访问同方法的属性——只能通过设置不同名称)

  4. 外部类要先创建对象,才能访问到局部内部类的成员

  5. 如果外部类和局部内部类的成员重名时,默认遵循就近原则

    ​ 但可用【外部类名.this.成员】来访问外部类的成员

+++

二、匿名内部类(没有类名)

1.基本介绍

  1. 定义位置:方法中、代码块中

  2. 本质是类,同时是一个对象,该类没有名字

  3. 优点:用完即丢,不占用过多空间

2.使用细节

同局部内部类

创建匿名内部类时,不能重写构造方法

+++

三、成员内部类(没static)

1.使用细节

  1. 可以直接访问外部类的所有成员

  2. 可以添加任意访问修饰符【因为他的地位就是一个成员】

  3. 作用域:整个类

  4. 成员内部类 访问 外部类——直接访问

  5. 外部类 访问 内部类 —— 创建对象,再访问

  6. 外部其它类 访问 成员内部类

    ​ a. 通过实例化外部类所生成的对象,来实例化内部列

    ​ b. 在外部类中编写一个方法,返回成员内部类

+++

四、静态内部类(有static)

1.使用细节

  1. 可以直接访问外部类的所有成员

  2. 可以添加任意访问修饰符【因为他的地位就是一个成员】

  3. 作用域:整个类

  4. 成员内部类 访问 外部类——直接访问【只能访问static修饰的成员】

  5. 外部类 访问 内部类 —— 创建对象,再访问

  6. 外部其它类 访问 成员内部类

    ​ a. 通过类名直接访问

    ​ b. 在外部类中编写一个方法,返回成员内部类

枚举(enum)

一、自定义类实现枚举

1.特点

  1. 构造器私有化

  2. 本类内部创建一组对象

    a. 使用final + static共同修饰

    b. 命名使用全部大写

  3. 对外暴露对象

  4. 可以提供 get方法,但不需要提供 set方法

+++

二、enum实现枚举

1.特点

  1. 使用使用关键字 enum 替代 class
  2. 默认继承 Enum类,父类的 toString方法 默认返回
  3. 创建语法: 常量名(实参列表)【写在行首】
  4. 使用无参构造器 创建枚举对象时,小括号可省略
  5. 当创建多个对象时 ,使用,号间隔,最后一个用 ;号结尾

+++

常用类

一、包装类

1.分类

高亮部分的包装类

基本数据类型 包装类
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double

二、String类

1.基本介绍

  1. String类 是保存字符串常量

  2. 字符串的字符使用Unicode字符编码【一个字符(不区分字母还是汉字)占两个字节】

  3. String 类实现了接口 Serializable 【String 可以串行化:可以在网络传输】

    ​ 接口 Comparable 【String 对象可以比较大小】

  4. 属性 private final char value[], 用于存放字符串内容

  5. value 是一个 final 类型, 不可以修改

    ​ 即 value 不能指向 新的地址,但是单个字符内容是可以变化


2.创建对象

  1. 直接赋值:String s = "king";

​ 区别:先从常量池查看是否有"king"的数据空间

​ 有则直接指向;没有则重新创建再指向

字符串s 最终指向的是常量池的空间地址

  1. 调用构造器:String s = new String("king");

​ 区别:先在堆中创建空间,里面维护了value属性,value指向常量池的"king"的数据空间

​ 有则直接通过value指向;没有重新创建再指向

字符串s 最终指向的是堆中的空间地址


3.常用方法

方法名 作用
boolean equals(Object o) 判断内容是否相等(区分大小写)
boolean equalsLgnoreCase(String s) 判断内容是否相等(忽略大小写)
int length() 获取字符串的长度
int indexOf(String s) 获取字符第一次出现的索引
int lastIndexOf(String s) 获取字符最后一次出现的索引
String substring(int i, int j) 截取指定范围的字符串
String trim() 去前后空格
char charAt(int i) 获取索引处的字符

【以下方法,均不会改变调用者的内容,只是返回一个新的处理过后的字符串】

方法名 作用
String toUpperCase() 转换成大写Stri
String toLowerCase() 转换成小写
String concat(String s) 拼接字符串
String replace(char old,char new ) 替换字符串
String split(String regex) 分割字符串
int compareTo(String s) 比较字符串
char[] toCharArray() 转换成字符数组

4.使用细节

  1. intern()方法,最终返回的是常量池的地址(对象)

  2. String a = "Hello" + "World" 等价于 String a = "HelloWorld"【只创建了一个对象】

  3. String a = "Hello"; String b = "World"; String c = a + b;

    【等价于StringBuilder sb = new StringBuider(); sb.append(a); sb.append(b);】

三、StringBuffer类

1.基本介绍

  1. 保存的是字符串常量,可以对字符串内容进行增删
  2. 线程安全
  3. StringBuffer是一个容器,长度是可变的
  4. 底层维护了char[] value数组,但不是final

2.String 和 StringBuffer的相互转换

//String -> StringBuffer        String str = "king";         //方式 1 使用构造器               StringBuffer stringBuffer = new StringBuffer(str);         //方式 2 使用的是 append 方法 StringBuffer         stringBuffer1 = new StringBuffer(); 		stringBuffer1 = stringBuffer1.append(str); //StringBuffer ->String         StringBuffer stringBuffer3 = new StringBuffer("king");         //方式 1 使用 StringBuffer 提供的 toString 方法         String s = stringBuffer3.toString();         //方式 2: 使用构造器来搞定 S        tring s1 = new String(stringBuffer3);

3.常用方法

方法名 作用
StringBuffer append(String/char/char[])
StringBuffer delete(int sta, int end) 删(左闭右开)
StringBuffer replace(int sta, int end, String s)
int index(String s)

4.使用细节

  1. String s = null; StringBuffer sb = new StringBuffer();

    sb.append(s);【调用了AbstractStringBuilder 的 appendNull方法,直接存入"null"字符串】

    StringBuffer sb1 = new StringBuffer(str);【NullpointerException 】

四、StringBuilder类

1.基本介绍

  1. 一个可变的字符序列
  2. 底层维护了 char[] value数,但不是 final
  3. 线程不安全
  4. 使用基本和StringBuffer类似

五、Math类

常用方法

public static int abs(int a)--返回参数的绝对值

public static double ceil(double a)--返回大于或等于参数的最小整数

public static double floor(double a)--返回小于或等于参数的最大整数

public static int round(float a)--按照四舍五入返回最接近参数的整数

public static int max(int a, int b)--返回最大值

public static int min(int a, int b)--返回最小值

public static double pow(double a, double b)--返回a的b次幂的值

public static double random()--返回[0.0,1.0)的double值

六、Array类

七、System类

集合(14)

一、Collection

1.常用方法

方法名 作用
boolean add(E e) 添加元素
E remove(int index) 删除并返回指定索引元素
boolean remove(Object o) 删除指定元素(整数要装箱)
boolean contains(Object o) 查看元素是否存在
int size() 获取元素个数
boolean isEmpty() 查看集合是否为空
void clear() 清空集合
boolean addAll(Collection c) 添加多个元素
boolean removeAll(Collection c) 删除多个元素
boolean containsAll(Collection c) 查看多个元素是否存在

2.集合遍历

        List list = new ArrayList();         list.add(new Dog("小黑", 3));         list.add(new Dog("大黄", 100));         list.add(new Dog("大壮", 8));

2.1迭代器遍历

boolean hasNext() ---- 判断集合中是否有下一个元素

E next() ---- 返回迭代的下一个元素

        Iterator iterator = list.iterator();         while (iterator.hasNext()) {             Object dog = iterator.next();             System.out.println("dog=" + dog);         }

2.2增强for遍历

        for (Object dog : list) {             System.out.println("dog=" + dog);         }

二、List

1.特点

有序 可重复 支持索引


2.常用方法

方法名 作用
void add(int index, Object ele) 在索引处插入指定元素
boolean addAll(int index, Collection eles) 在索引处添加多个元素
Object get(int index) 获取指定索引处的元素
int indexOf(Object obj) 返回该元素在集合中首索引
int lastIndexOf(Object obj) 返回该元素在集合中末索引
Object remove(int index) 删除索引处的元素,并返回此元素
Object set(int index, Object ele) 替换掉指定索引位置的元素
List subList(int fromIndex, int toIndex) 返回 [fromIndex,toIndex) 处的子集合

3.集合遍历

3.1for循环遍历

//普通for循环遍历for (int i = 0; i < list.size(); i++) {    Student s = list.get(i);    System.out.println(s.getName() + "," + s.getAge());}//增强for循环遍历for (Student s : list) {    System.out.println(s.getName() + "," + s.getAge());}

3.2迭代器(ListIterator)

常用方法 作用
E next() 返回迭代中的下一个元素
boolean hasNext() 判断是否存在下一个元素
E previous() 返回迭代中的上一个元素
boolean hasPrevious() 判断是否存在上一个元素

4.子类对象

4.1ArrayList

  1. ArrayList底层中维护了一个Object类型的数组【Object[] elementData】
  2. 使用无参构造器时,则初始化容量为0,第一次扩容为10,再次扩容为之前的1.5倍
  3. 使用有参构造器时,初始化为指定大小,再次扩容为之前的1.5倍
  4. 线程不安全,效率高

4.2Vector

  1. Vector底层中维护了一个Object类型的数组【Object[] elementData】
  2. 使用无参构造器时,则初始化容量为10,再次扩容为之前的2倍
  3. 使用有参构造器时,初始化为指定大小,再次扩容为之前的2倍
  4. 线程安全,效率不高

4.3LinkedList(链表)

  1. LinkedList底层中维护了一个双向链表
  2. 对于元素的添加和删除,效率较高

三、Set

1.特点

无序【添加和取出的顺序不一致,但取出顺序固定】

不可重复【hash() 和 equals()】

不支持索引


2.HashSet添加元素的实现【底层分析】

  1. 先获取元素的哈希值( hashCode方法 )

  2. 对哈希值进行运算,得出一个 存放在哈希表中的位置号

  3. 如果该位置上没有其他元素,则直接存放

    如果该位置上存在其他元素,则需要进行 equals 判断:

    ​ 若相等,则不添加;否则则以链表的方式添加

【注意:在Java8中,如果一条链表的元素个数(TREEIFY_THRESHOLD) 到达 8(默认) ,

​ 并且table的大小(MIN_TREEIFY_CAPACITY) >= 64,在下一次添加时就会进行树化。

​ 否则仍然采用数组扩容机制】


3.HashSet的扩容和转成红黑树机制【底层分析】

  1. 第一次添加时,table 数组扩容到 16,临界值(threshold) 是 16 * 加载因子(loadFactor = 0.75)
  2. 如果table数组使用到了临界值,就会按 2 倍来扩容,并重新计算临界值

4.子类对象

4.1HashSet

HashSet 底层是 HashMap

4.2LinkedHashSet

LinkedHashSet 是 HashSet 的子类

LinkedHashSet 底层是:数组 + 双向链表【有序】

每一个节点有 before 和 after属性, 保证了有序性

4.3TreeSet

可定义的有序,不含相同元素

有参构造:TreeSet() -- 根据元素的自然排序进行排序

自定义有序

  	1. 调用有参构造函数:直接实例化Comparator接口(匿名内部类),重写compare方法	2. 作为 key 的实现类,继承Comparable接口,并重写 compareTo方法

四、Map

1.特点

  1. Map 与 Collection并列存在。用于保存具有映射关系的数据:Key--Value
  2. key 和 value 可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. key 不允许重复,value 可以重复
  4. 当 key重复时,value 会被新的替换

2.遍历方式

2.1 通过 keySet 来获取 value

		Set keyset = map.keySet()                 		//(1)	增强 for             for (Object key : keyset) {             System.out.println(key + "-" + map.get(key));        }        //(2)	迭代器        Iterator iterator = keyset.iterator();         while (iterator.hasNext()) {             Object key = iterator.next();             System.out.println(key + "-" + map.get(key));         }

2.2 通过 EntrySet 来获取 k-v

        Set entrySet = map.entrySet();        //(1) 增强 for            for (Object entry : entrySet) {                         Map.Entry m = (Map.Entry) entry; //将 entry 转成 Map.Entry             System.out.println(m.getKey() + "-" + m.getValue());         }        //(2) 迭代器                Iterator iterator3 = entrySet.iterator();         while (iterator3.hasNext()) {             Object entry = iterator3.next();             //System.out.println(next.getClass()); //HashMap$Node            //HashMap$Node -实现-> Map.Entry (getKey,getValue)                         Map.Entry m = (Map.Entry) entry; //向下转型 Map.Entry             System.out.println(m.getKey() + "-" + m.getValue());         }

3.子类对象

3.1HashMap

  1. HashMap是以 key-value对的方式来存储数据的(HashMap$Node类型)

    【key-value ----> HashMap$Node ----> Map$Entry 】

  2. key 不可以重复,value可以重复。两者都可以为 null

  3. 如果添加相同的 key,则会覆盖原来的value

  4. 不保证映射顺序【底层是以hash表的方式来存储的】

  5. 线程不安全

  6. 扩容机制和HashSet一样,因为 HashSet的底层就是 HashMap

3.2Hashtable

  1. HashMap是以 key-value键值对的方式来存储数据的
  2. key 不可以重复,value可以重复。两者都不可以为 null
  3. 如果添加相同的 key,则会覆盖原来的value
  4. 线程安全

3.3Properties

  1. . Properties 继承 Hashtable
  2. 可以通过 k-v 存放数据,key 和 value 不能为 null

3.4TreeMap

可定义的有序,不含相同元素,键值不能为null

有参构造:TreeMap() -- 根据元素的自然排序进行排序

自定义有序

  	1. 调用有参构造函数:直接实例化Comparator接口(匿名内部类),重写compare方法	2. 作为 key 的实现类,继承Comparable接口,并重写 compareTo方法

五、如何选择集合实现类

image-20211004154757930

六、Collections

1.常用方法

常用方法 作用
reverse(List list) 反转集合元素的顺序
shuffle(List list) 对集合元素进行随机排序
sort(List list) 自然顺序,进行升序排序
sort(List list,Comparator c) 自定义排序
swap(List list,int i, int j) 将索引为i,j的元素互换位置
Object max(Collection c) 自然顺序,返回集合中的最大元素
Object max(Collection c,Comparator com) 自定义排序,返回集合中的最大元素
int frequency(Collection c,Object obj) 返回集合中元素的出现次数
void copy(List dest,List src) 将 src 中的内容复制到 dest 中

泛型(15)

一、基本介绍

  1. 泛型,又称参数化类型,是JDK5.0出现的新特性,解决数据类型的安全性问题

  2. 在类声明或实例化时只要指定号需要的具体的类型即可

  3. 作用:可以在类声明时通过一个标识符表示类中某个属性的类型、方法的返回值的类型或参 数类型

  4. 好处:编译时,检查添加元素的类型,提高了安全性

    ​ 减少了类型转换的次数,提高效率

二、泛型分类

1.泛型类

定义格式:修饰符 class 类名<类型>


2.泛型方法

定义格式:修饰符 <类型> 返回值类型 方法名(类型 变量名)


3.泛型接口

定义格式:修饰符 interface 接口名<类型>

三、使用细节

  1. 注意:具体调用时的形参,只能是引用类型类型

  2. 在给泛型指定具体类型后,可以传入该类型或者其子类类型

  3. ArrayList arrayList = new ArrayList(); 【泛型默认为 Object】

  4. 泛型不具备继承性

    ​ List

posted @ 2021-10-16 20:13  微风赋值  阅读(88)  评论(0)    收藏  举报