第一阶段
基础部分
前置知识点
一个源文件中只能有一个public类,其他的类个数不限
编译后每一个类都对应一个.class文件
如果源文件包含一个public类,则该文件必须按该类名命名
可以将main写在非public类中,然后指定运行非public类,这样入口方法就是非public的main
1、转义字符
2、文档注释
3、环境变量的作用是为了在dos的任意目录,都可以使用java和javac命令
4、先配置JAVA_HOME,指向jdk安装的主目录
5、编辑path环境变量,增加%JAVA_HOME%\bin
变量
变量是程序的基本组成单位
变量表示内存中的一个存储区域
数据类型
每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间
long 型常量后必须加l或L
浮点型常量默认为double型
float型常量后必须加f或F
多种数据类型混合运算时,系统自动将数据转换成容量最大的那种数据类型,再进行运算
(byte, short)和 char不会相互自动转换
byte, short, char三者之间可以计算,计算时首先转换成int
boolean 不参与转换
String转基本数据类型——通过基本数据类型的包装类parseXX
Integer.parseInt(),
Double.parseDouble(),
Float.parseFloat(),
Long.parseLong(),
Boolean.parseBoolean(),
Byte.parseByte(),
Short.parseShort()
运算符
取模%的本质: a % b = a - a / b * b 取模的结果与被除数的符号一致
短路与 与 逻辑与
&&短路与: 如果第一个条件为false, 则不会再判断第二个条件,效率高
&逻辑与: 不管第一个条件是否为false,第二个条件都会判断, 效率低
短路或 与 逻辑或
||短路或:第一个条件为true,第二个条件就不会判断,效率高
|逻辑或:不管第一个是否为TRUE,第二个条件都会判断,效率低
逻辑异或: a^b ,a,b不同时,结果为true,否则为false
标识符命名规范:
包名:多单词组成时所有字母都小写
类名、接口名:多单词组成时所有单词的首字母大写
变量名、方法名:驼峰命名法
常量名:所有字母都大写,多单词时每个单词用_连接
键盘输入语句
需要获取用户输入的数据,就可以使用键盘输入语句来获取。
Input.java,需要一个扫描器(对象),就是scanner
步骤:
导入该类所需要的包,java.util.*
import java.util.Scanner
导入该类对象(声明变量)
Scanner scanner = new Scanner(System.in)
调用里面的功能(next()/ nextInt()/ nextDouble()/ nextFloat()....)
String str = scanner.next() // 接收用户输入
进制
二进制--以0b或0B开头
八进制--以0开头
十六进制--以0x或0X开头, A-F不区分大小写
进制转换
十进制转二进制(转八进制十六进制同理)
二进制转八进制(十六进制)
从低位开始,将二进制数每三位(四位)一组,转成对应的八进制数(十六进制)即可
八进制(十六进制)转二进制
将八进制(十六进制)的每一位,转换成对应的一个3位(4位)的二进制数即可
原码、反码、补码
位运算
按位与&:两个全为1,结果为1,否则为0
按位或|: 有一个为1,结果为1,否则为0
按位异或^:两个一个为0一个为1,结果为1,否则为0
按位取反~:0变1,1变0
位运算符
分支
如果判断的具体数值不多,且都符合byte, enum, short, int, char, String这六种类型,建议用switch
for(; ;) {} 表示无限循环即死循环
循环初始化可以有多条语句,但要求类型一致,且用逗号隔开,循环变量迭代也可以有多条变量迭代语句,用逗号隔开
数组、排序、查找
数组的定义:
数据类型 数组名[] = new 数据类型[大小] 如:int arr= new int[5]
数据类型[] 数组名 = new 数据类型[大小] 如:int[] arr = new int[5]
动态初始化
声明
数据类型 数组名[] 或 数据类型[] 数组名 如: int arr [] , int[] arr
创建数组
数组名 = new 数据类型[大小] 如: arr = new int[10]
静态初始化
数据类型 数组名[] = {元素值, 元素值, 元素值, ...}
arr2 = arr1 ===> arr1的地址复制给arr2 <====> arr2改变,arr1跟着改变
数组扩容
定义一个新的数组newArr,定义时容量比扩容的数组arr大
遍历arr,将arr的数据拷贝到newArr
把扩容的内容添加到newArr
让arr指向newArr,arr = newArr, 原来的arr会被销毁
类与对象
类是抽象的、概念的,代表一类事物,例如人类、猫类……,即它是数据类型
对象是具体的、实际的,代表一个具体事物,即 是实例
类是对象的模板,对象是类的一个个体,对应一个实例
成员变量 = 属性 = field字段
属性是类的一个组成部分,一般是基本数据类型,也可以是引用数据类型(对象、数组)
java内存的结构分析
栈: 一般存放基本数据类型(局部变量)
堆: 存放对象(Cat cat, 数组等)
方法区:常量池(常量,比如字符串等), 类加载信息
java创建对象流程分析
先加载类信息(属性和方法信息,只会加载一次)
在堆中分配空间,进行默认初始化
把地址赋值给类名,类名就指向对象
进行指定初始化
方法调用细节:
调用带参数的方法,传入的参数要与对应参数数据类型相同或能被对应形参的数据类型兼容
方法返回的数据类型一定要与定义方法的类型一致
方法中不能嵌套定义方法
同一个类中的方法可以直接调用
跨类调用方法,需要通过对象名调用
成员方法中接受一个数组,在方法中修改该数组,原来的数组也会被改变——数组是引用类型,形参数组接收到的是原来数组指向的地址
递归
递归实例--迷宫
递归实例 -- 汉诺塔
方法重载 -- 方法名相同,参数数量或参数类型不同
可变参数 -- 同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法
基本语法 -- 访问修饰符 返回类型 方法名(数据类型... 形参名)
数据类型... 代表的是可以接收0或者多个可变参数
使用可变参数时,形参可以当作数组来使用
可变参数可以和普通参数一起放在形参的列表,但是可变参数必须放到最后
一个形参列表中只能出现一个可变参数
构造器 -- 构造方法
-- 是类的一种特殊的方法,主要作用是完成对新对象的初始化
基本语法 -- [修饰符] 方法名(形参列表) { 方法体 }
构造器没有返回值
方法名和类名字必须一致
一个类可以定义多个不同的构造器,即构造器重载
构造器是完成对象的初始化,不是创建对象
构造器的调用系统完成 -- 在创建对象时,系统会自动调用该类的构造器完成对对象的初始化
使用 -- 在new一个对象时,直接通过构造器指定属性值
如 Person personInfo = new Person('name', 'age')
如果没有定义构造器,系统会自动给类生成一个默认无参构造器
一旦定义了构造器,默认的构造器就被覆盖了,不能再使用,除非显式的定义一下
this
Java虚拟机会给每个对象分配this,代表当前对象
this用于区分当前类的熟悉和局部变量
this不能在类定义的外部使用,只能在类定义的方法中使用
this访问构造器语法:this(参数列表);只能在构造器中使用,且必须放置在第一条语句
中级部分
IDEA
常用快捷键 -- 设置> 键盘映射>查询
补全代码 -- alt + /
包
包命名规范
常用的包
包相关细节
访问修饰符
封装 -- 面向对象编程
封装就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作
封装的好处
-- 可以隐藏实现的细节
-- 可以对数据进行验证,保证安全合理
封装的实现步骤
将属性进行私有化private(不能直接修改属性)
提供一个公共的set方法,用于对属性判断并赋值
提供一个公共的get方法,用于获取属性的值
—— get 与 set 方法可以通过快捷键-- alt+insert, 选择getter与setter
构造器与setXXX()
在构造器中调用set方法
继承
继承可以解决代码复用
继承基本语法
class 子类 extends 父类 { }
子类就会自动拥有父类定义的属性和方法
父类又叫超类,基类
子类又叫派生类
继承注意事项
子类继承了所有的属性和方法,但是私有属性不能在子类直接访问,要通过公共的方法去访问
子类必须调用父类的构造器,完成父类的初始化
当创建子类对象时,不管使用子类的那个构造器,默认情况下总会调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成父类的初始化工作,否则,编译不会通过
如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)
super在使用时,需要放在构造器第一行
super()和this()都只能放在构造器的第一行,所以这两个方法不能共存于一个构造器
Java所有类都是Object的子类,Object是所有类的基类
父类构造器的调用不限于直接父类,将一直往上追溯到Object类(顶级父类)
子类最多只能继承一个父类(指直接继承),即Java是单继承机制
不能滥用继承,子类和父类之间必须满足is-a的逻辑关系
所有的构造器里都有一个默认的super()
Super
super代表父类的引用,用于访问父类的属性、方法、构造器
基本语法
com.sxy.super_ 包下 super.java
访问父类的属性 -- super.属性名
访问父类的方法 -- super.方法名(参数列表)
访问父类的构造器 -- super(参数列表) -- 只能放在构造器的第一句,只能出现一句
方法重写/覆盖
方法重写/覆盖就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么就说这个子类的方法覆盖了父类的方法
方法重写注意事项
子类方法的参数、方法名称要和父类的完全一样
子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类--如父类返回Object,子类返回String
子类方法不能缩小父类方法的访问权限
重载与重写
多态
基本介绍
方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承基础之上的
具体体现
方法的多态 -- 重载和重写体现多态
对象的多态 (核心、重点)
一个对象的编译类型和运行类型可以不一致
编译类型在定义对象时,就确定了,不能改变
运行类型是可以变化的
编译类型看定义时 = 的左边,运行类型看 = 的右边
注意事项
多态的前提是:两个对象(类)存在继承关系
多态的向上转型
本质: 父类的引用指向了子类的对象
语法: 父类类型 引用名 = new 子类类型();
特点: 编译类型看左边,运行类型看右边
可以调用父类中的所有成员(需遵守访问权限)
不能调用子类中特有成员 -- 因为编译阶段能调用哪些成员是由编译类型决定的
最终运行效果看子类的具体实现,即调用方法时从子类(运行类型)开始查找
多态的向下转型
语法: 子类类型 引用名 = (子类类型) 父类引用
只能强转父类的引用,不能强转父类的对象
要求父类的引用必须指向的是当前目标类型的对象
向下转型后,可以调用子类类型中的所有成员
属性没有重写之说,属性的值看编译类型
instanceOf 比较操作符,用于判断对象的运行类型是XX类型或者XX类型的子类型
Java的动态绑定机制(重要)
当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
多态的应用
数组多态 -- 数组的定义类型为父类类型,保存的实际元素为子类类型
参数多态 -- 方法定义的形参类型为父类类型,实参类型允许为子类类型
equals方法
equals与 ==
== : 比较运算符,即可以判断基本类型,又可以判断引用类型
== : 如果判断基本类型,判断的是值是否相等
== : 如果判断引用类型,判断的是地址是否相等,即判断是不是同一个对象
equals是object中的方法,只能判断引用类型
默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等
查看源码方法 -- 配置下图 ==> ctrl+b或者右键go to
hashCode
toString()
直接输出一个对象时,toString默认被调用
System.out.println(object) == System.out.println(object.toString())
finalize方法
实际开发中,几乎不会用finalize方法
断点调试
第二阶段
面向对象编程(高级)
类变量(static 静态变量)
类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样,任何一个该类的对象去修改它时,修改的也是同一变量
定义: 访问修饰符 static 数据类型 变量名
static 访问修饰符 数据类型 变量名
访问方法:
类名.类变量名 或者 对象名.类变量名
static变量是同一个类所有对象共享
static变量在类加载的时候就生成了
类变量随着类的加载而创建,所以即使没有创建对象实例,也可以访问
类变量的访问,必须遵守相关的访问权限
类方法
当方法使用了static修饰后,该方法就变成了静态方法
静态方法可以访问静态属性/静态变量
类方法的调用
类名.方法名 或者 对象名.方法名 (前提是满足相关权限)
main语法说明
main方法的形式: public static void main(String[] arg) {}
main方法是Java虚拟机调用的
Java虚拟机需要调用类的main方法,所以该方法的权限必须是public
Java虚拟机在执行main方法时不必创建对象,所以该方法必须是static
该方法接收String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数
Java执行的程序 参数一 参数二 参数三
静态方法Main,要访问本类的非静态成员,需要先创建本类对象,再调用
代码块
代码块,又称为初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来
但和方法不同,没有方法名,没有返回,没有参数,只有方法体,且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用
基本语法
[修饰符] { 代码 };
调用构造器时,会首先调用代码块
单例模式
final关键字
final 可以修饰类、属性、方法、局部变量
使用final场景
当不希望类被继承时
当不希望父类的某个方法被子类重写/覆盖时
当不希望类的某个属性的值被修改时
当不希望某个局部变量被修改时
注意事项
final修饰的属性又叫常量,一般用XX_XX_XX命名
final修饰的属性在定义时,必须赋初值,并且以后不能修改,赋值位置可以在:
定义时:如public final double TAX_RATE = 0.8
在构造器中
在代码块中
如果final修饰的属性是静态的,则初始化的位置只能是①定义时②在静态代码块, 不能在构造器中赋值
final类不能继承,但可以实例化对象
如果类不是final类,但是含有final方法,则该方法虽然不能重写,但可以被继承
一般来说,如果一个类已经是final类了,就没必要再将方法修饰成final方法
final不能修饰构造方法/构造器
final和static往往搭配使用,效率更高,底层编译器做了优化处理
包装类(Integer , Double, Float, Boolean等都是final),String也是final类
抽象类
当父类的某些方法需要声明,但又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类
父类方法不确定性的问题,考虑将该方法定义为抽象方法,抽象方法就是没有实现的方法,没有实现的方法,就是没有方法体的方法。当一个类中存在抽象方法时,需要将该类声明为抽象类。一般来说,抽象类会被继承,由其子类实现抽象方法。
注意事项
抽象类不能被实例化
抽象类不一定有抽象方法,但包含抽象方法的类一点声明为抽象类
abstract只能声明类和方法,不能修饰其他的
抽象类可以有任意成员,比如非抽象方法、构造器、静态属性等
抽象方法不能有主体
如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract
抽象方法不能使用private, final和static来修饰,因为这些关键字都是和重写相违背的
接口
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来
语法: interface 接口名 {}
class 类名 implements 接口 { 自己的属性; 方法; 必须实现的接口的抽象方法 }
在Jdk7.0之前,接口里的所有方法都没有方法体
在Jdk8.0之后接口类可以有静态方法,默认方法,即接口中可以有方法的具体实现,但需要default修饰
在接口中,抽象方法可以省略abstract关键字
注意事项
接口不能被实例化
接口中所有的方法都是public,接口中抽象方法,可以不用abstract修饰
一个普通类实现接口,就必须将该接口的所有方法都实现,alt+enter快速实现
抽象类实现接口,可以不用实现接口的方法
一个类同时可以实现多个接口
接口中的属性,只能是final的,而且是public static final修饰符
接口中属性的访问形式: 接口名.属性名
一个接口不能继承其他类,但可以继承多个其他接口 interface A extends B,C{}
接口的修饰符,只能是public和默认
继承与实现:
子类继承了父类,就自动拥有了父类的功能
子类需要扩展功能,可以通过实现接口的方法进行扩展
继承的价值主要在于解决代码的复用性和可维护性
接口的价值主要在于设计,设计好各种规范(方法),让其他类去实现这些方法
接口比继承更加灵活
接口在一定程度上实现代码解耦[即接口规范性+动态绑定]
接口的多态性
多态参数
多态数组
多态传递
内部类
一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类
内部类最大的特点就是可以直接访问私有属性,且可以体现类与类之间的包含关系
类的五大成员: 属性、方法、构造器、代码块、内部类
基本语法:
class outerClass { // 外部类
class innerClass { // 内部类
}
}
class otherClass { // 其他外部类
}
局部内部类是定义在外部类的局部位置,比如方法中,并且有类名
1.可以直接访问外部类的所有成员,包含私有的
2.不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final 修饰,因为局部变量也可以使用final
3.作用域: 仅仅在定义它的方法或代码块中
4.局部内部类---访问---->外部类的成员 [访问方式: 直接访问]
5.外部类---访问---->局部内部类的成员访问方式:创建对象,再访问(注意: 必须在作用域内)
6.外部其他类---不能访问----->局部内部类(因为 局部内部类地位是一个局部变量)
7.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问:
System.out.println("外部类的n2="+ 外部类名.this.n2)
匿名内部类
匿名内部类是定义在外部类的局部位置,如果方法中,并且没有类名,同时是一个对象
基本语法 : new 类名或者接口(参数) {
类体
}
jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 outer04$1实例,并且把地址返回
匿名内部类使用一次就不能再使用了
匿名内部类与创建对象的区别: 匿名内部类有大括号
参数会传入构造器
匿名内部类既是一个类的定义,本身也是一个对象,所以既有类的特征,也有创建对象的特征,因此可以调用匿名内部类方法
可以直接访问外部类的所有成员,包括私有的
不能添加访问修饰符,因为它的地位就是一个局部变量
作用域: 仅仅再定义它的方法或代码块中
匿名内部类访问外部成员方法: 直接访问
外部其他类不能访问匿名内部类,因为匿名内部类的地位是一个局部变量
如果外部类和内部类的成员重名时,匿名内部类访问遵循就近原则,内部类想访问外部类的成员时,可以使用 外部类名.this.成员 的方法访问
匿名内部类可以当作实参直接传递
成员内部类
定义在外部类的成员位置上
可以访问外部类所有成员,包含私有
可以添加任意访问修饰符,因为它的地位是成员
作用域和外部类的其他成员一样,为整个类体,在外部类的成员方法中创建成员内部类对象,再调用方法
成员内部类---访问---->外部类(比如:属性)[访问方式:直接访问]
外部类---访问------>内部类访问方式: 创建对象,再访问
外部其他类---访问---->成员内部类 : 成员类构造方法返回内部类 或者
如果外部类和内部类的成员重名时,成员内部类访问遵循就近原则,内部类想访问外部类的成员时,可以使用 外部类名.this.成员 的方法访问
静态内部类
枚举和注解
枚举是一组常量的组合,属于一种特殊的类,只包含一组有限的特定的对象
枚举的实现方式:自定义实现枚举,enum关键字实现枚举
自定义实现枚举
enum关键字实现枚举
使用enum关键字时,会隐式继承enum类
注意事项:
使用enum关键字后,就不能再继承其他类了,因为enum会隐式的继承Enum,而Java是单继承机制
枚举类和普通类一样,可以实现接口
enum 类名 implement 接口1, 接口2{}
JDK内置的基本注解
注解(Annotation)也被称为元数据(metaData),用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息
和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息
在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗代码和XML配置等
使用Annotation时要在其前面增加@符号,并把该Annotation当作一个修饰符使用,用于修饰它支持的程序元素
三个基本的Annotation
@Override: 限定某个方法,是重写父类方法,该注解只能用于方法
@Deprecated: 用于表示某个程序元素(类、方法等)已过时
@SuppressWarnings: 抑制编译器警告
如果发现了@interface,表示一个注解类
元注解:对注解进行注解
Exception 异常
基本概念
Java语言中,将程序执行中发生的不正常的情况称为"异常"(语法错误和逻辑错误不是异常)
执行过程中异常可分为两类
Error: Java虚拟机无法解决的严重问题,如JVM系统内部错误、资源耗尽等,程序会崩溃
Exception: 其他编程错误或偶然的外在因素导致的一般性问题,可以使用针对性代码进行处理,例如空指针访问、试图读取不存在的文件、网络连接中断等。Exception分为两大类: 运行时异常和编译时异常
异常体系图
常见的运行异常
NullPointerException 空指针异常: 当应用程序试图在需要对象的地方使用null时,抛出该异常
ArithmeticalException 数学运算异常: 出现异常的运算条件时抛出
ArrayIndexOutOfBoundsException 数组下标越界异常: 非法索引访问数组时抛出
ClassCastException 类型转换异常: 试图将对象强制转换成不是实例的子类时抛出
NumberFormatException 数字格式不正确异常: 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时抛出
异常处理机制
try代码块可能有多个异常
可以使用多个catch来捕获多个异常
要求子类异常写前面,父类异常写后边
可以进行try-finall配合使用,相当于没有捕获,如果有异常程序会崩溃
throws
注意事项
自定义异常
throw 和throws的区别
常用类
包装类
包装类的分类
针对八种数据类型相应的引用类型--包装类
有了类的特点,就可以调用类中的方法
装箱和拆箱
包装类方法
Integer创建机制
只要有基本数据类型,判断的是值是否相等
String类
String结构剖析
String创建剖析
String特性
String是一个final类,代表不可变的字符序列
字符串是不可变的,一个字符串对象一旦被分配,其内容是不可变的
String方法
补充:a.compareTo(b)比较的时候,先比较长度,如果长度不一样长,则返回a.length - b.length;如果一样长,就比较字符,比如:"jcck" 与"jack" ,c比a大2,则返回2;如果长度字符都一样,则返回0
StringBuffer 和StringBuilder类
StringBuffer
StringBuffer代码可变的字符序列,可以对字符内容增删
很多方法与String相同,但StringBuffer是可变长度的
StringBuffer是一个容器
StringBuffer构造器
StringBuffer方法
StringBulider类
Math类
Math类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数,均为静态方法
常用方法
Date日期类、Calendar日历类以及新的日期
第一代日期类
new Date() 获取当前系统时间
new Date(毫秒数) 通过指定毫秒数获取时间
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss") 参数为要转换的格式
可以把一个格式化的String转换成对应的Date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
String str = "2023-02-03 12:00:00"
Date parse = sdf.parse(str)
使用的sdf格式需要和str格式一样,否则会抛出异常
第二代日期类
主要是Calendar(日历)类
Calendar类是一个抽象类
获取Calendar实例对象 -- Calendar.getInstance();
获取某个日历对象: Calendar实例对象.get(Calendar.YEAE)
获取月时要加1:Calendar实例对象.get(Calendar.MONTH + 1)
第三代日期类
使用now() 返回表示当前日期时间的对象
LocalDate.now() LocalTime.now() LocalDateTime.now()
格式化
// 创建DateTimeFormatter对象
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(格式)
// 格式化日期
String str = dtf.format(日期对象)
时间戳 Instant (类似于Date)
Instant instant = Instant.now() // 创建当前时间戳的对象
Instant --> Date
Date date = Date.from(instant)
Date --> Instant
Instant instant = date.toInstant()
System类
arraycopy 参数含义
Arrays类
Array 的排序方法
冒泡排序
Arrayy.sort(arr) 因为数组是引用类型,所以会直接影响到实参arr
可以传入一个接口Comparator实现定制排序,调用定制排序时,传入两个参数
排序的数组
实现了Comparator接口的匿名内部类,要求实现compare方法
Array.binarySearch 如果没有找到,则返回 -(low+1)
Array.sort(arr, new Comparator() {
@override
public int compare(Object obj1, Object obj2) {
Integer int1 = (Integer)obj1;
Integer int2 = (Integer)obj2;
return int2 - int1; // 从大到小排列,如果从小到大排列,return int1 - int2
}
});
copyOf
第二个参数是要复制的元素个数
如果要复制的长度大于arr.length,就在新数组的后边添加 null
如果要复制的长度小于0,则抛出异常 NegativeArraySizeException
该方法底层使用的是System.arraycopy()
BigInteger类和BigDecimal类
应用场景
BigInteger适合保存比较大的整型
BigDeccimal适合保存精度更高的浮点型
BigInteger常见方法 -- 加减乘除
BigInteger.add(BigInteger)
BigInteger.substract(BigInteger)
BigInteger.multiply(BigInteger)
BigInteger.divide(BigInteger)
BigDecimal方法同上
当BigDecimal调用divede时,如果最后是无限循环小数,则可能抛出异常ArithmeticException
解决方法: 指定精度--BigDecimal.ROUNT_CEILING,如果有无限循环小数,会保留分子的精度 bigDecimal.devide(bigDecimal, BigDecimal.ROUNT_CEILING)
集合
集合的优点
可以动态的保存任意多个对象
提供了一系列方便的操作对象的方法
使用集合添加、删除新元素的示意代码
集合框架体系
集合主要是两组(单列集合, 双列集合)
Collection 接口有两个重要的子接口 List Set, 他们的实现子类都是单列集合
Map接口的实现子类是双列集合,存放的K-V
Collection
Collection接口实现类的特点
Collection实现子类可以存放多个元素,每个元素可以是Object
有些Collection的实现类,可以存放重复元素,有些不可以
有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
Collection接口没有直接的实现类,是通过它的子接口List和Set来实现的
Collection方法
Collection接口实现遍历的方法
迭代器 -- Iterator
当迭代器循环结束后,iterator.next()指向最后一个元素,如果在调用next(), 会抛出异常;如果想要再次迭代,需要重置迭代器:iterator = col.interator();
快捷方式: itit
增强for循环 -- 底层调用了迭代器
快捷方式: I
List接口和方法
add方法,如果不加index,则默认加到List最后
set方法,index必须在List索引中存在,如果不存在,会抛出异常
subList返回的子集合 fromIndex <= subList < toIndex
List的三种遍历
ArrayList
注意事项
ArrayList底层操作机制源码分析
Vector
注意事项
Vector与ArrayList比较
LinkedList
底层操作机制
Set接口
HashSet
执行add方法时,如果添加成功会返回true,否则返回false。如果在HashSet中add已经存在的元素,则会返回false
HashSet底层机制说明
LinkedHashSet
Map
Collections
泛型
需要引入泛型的原因:
泛型的好处:
泛型介绍:
泛型语法
注意事项:
T,E只能是引用类型
在指定泛型具体类型后,可以传入该类型或者其子类类型
泛型使用形式:
List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<>();
List list3 = new ArrayList(); 默认给的泛型是<E>, E就是Object
自定义泛型
自定义泛型方法中,定义的泛型<T, R>是给方法参数使用的,而不是返回类型
泛型继承和通配符
泛型不具备继承性
<?>: 支持任意泛型类型
<? extends A>: 支持A类以及A的子类,规定了泛型的上限
<? super A>: 支持A类以及A类的父类,不限于直接父类,规定了泛型的下限
其他知识点补充
三元运算符
三元运算符是一个整体,如 Ojbect obj = true? new Integer(1) : new Double(2.1) ,最终返回的是1.0。 三元运算符计算的时候会提升到语句中的最高精度
Java绘图坐标体系