Java版本
Java SE 版本 | JDK版本 | 发布时间 | 开发代号 |
---|---|---|---|
Oak | 1995-05-23 | Oak(橡树) | |
Java 1.0 | JDK 1.0 | 1996-01-23 | |
Java 1.1 | JDK 1.1 | 1997-02-18 | |
J2SE 1.2 | JDK 1.2 | 1998-12-04 | Playerground(运动场) |
J2SE 1.3 | JDK 1.3 | 2000-05-08 | Kestrel(美洲红隼) |
J2SE 1.4 | JDK 1.4 | 2002-02-13 | Merlin(灰背隼) |
Java SE 5.0 | JDK 1.5 | 2004-09-29 | Tiger(老虎) |
Java SE 6 | JDK 1.6 | 2006-12-11 | Mustang(野马) |
Java SE 7 | JDK 1.7 | 2011-07-28 | Dolphin(海豚) |
Java SE 8 | JDK 1.8 | 2014-03-18 | Spider(蜘蛛) |
Java SE 9 | JDK 1.9 | 2017-09-21 | |
Java SE 10 | JDK 10 | 2018-03-21 | |
Java SE 11 | JDK 11 | 2018-09-25 | |
Java SE 12 | JDK 12 | 2019-03-20 |
static
详见Java中的static。
面向对象
父类中的方法默认可以被子类重写,加上final
则只能被继承不能被重写。而加了final的类无法被继承。
父类的构造方法不能被继承,但子类会调用父类的构造方法。Java虚拟机构造子类对象前会先构造父类对象,父类对象构造完成之后再来构造子类特有的属性,这被称为内存叠加
。而Java虚拟机构造父类对象会执行父类的构造方法,所以子类构造方法必须调用super()
即父类的构造方法。如果子类的构造方法中没有显示地调用父类构造方法,则系统默认调用父类无参数的构造方法。
子类重写父类的方法,作用域不能比父类小。如Son重写Father的output方法,该方法在Father中是protected的,那么Son中重写只能是public或protected,不能是default和private。
只有抽象类中才能有抽象方法,抽象方法不能有函数体,非抽象的子类必须实现其函数体。
基本类型 和 包装类
有时我们需要基本数据类型也有对象的特征,因此出现了包装类,将基本数据类型包装起来使其具有对象的性质,并添加了属性和方法。
基本数据类型与包装类型的区别
- 默认值不同:基本类型的值是
0
、false
等,包装类默认为null
- 初始化方式不同:包装类要用
new
的方式创建,基本类型不需要 - 存储方式不同:基本类型主要保存在栈上,包装类对象保存在堆上
== 和 equals()
对于基本数据类型如,==
比较的是值,且基本类型没有equals
方法。
对于包装类等对象,==
比较的是地址,equals
方法默认比较的也是地址,但可以重写来自定义比较逻辑。
1 | public static void main(String[] args) { |
双引号直接写的字符串是在常量池之中,而new的对象则不在池之中。
包管理
修饰符 | 当前类 | 同一包内 | 同一包内的子类 | 不同包内的子类 | 其他包 |
---|---|---|---|---|---|
public | √ | √ | √ | √ | √ |
protected | √ | √ | √ | 可访问父类的protected,不可访问父类对象的protected | × |
default | √ | √ | √ | × | × |
private | √ | × | × | × | × |
instanceof:判断一个变量是否是某个类的实例
1 | // Car 是 Vehicle 的子类 |
Math
原始值 | floor(向下取整) | round(四舍五入) | ceil(向上取整) |
---|---|---|---|
2.7 | 2 | 3 | 3 |
2.3 | 2 | 2 | 3 |
-2.3 | -3 | -2 | -2 |
-2.7 | -3 | -3 | -2 |
floor是地板的意思,ceil是天花板,就很好记了
try & catch & finally
在try
中存在return
的情况下,会把try中return的值存到栈帧的局部变量表中,然后去执行finally
语句块,最后再从局部变量表中取回return的值返回。
当try和finally里都有return时,会忽略try的return,而使用finally的return。
正常情况下,finally中的代码一定会得到执行。但是如果我们将执行try-catch-finally代码块的线程设置为守护线程,或者在fianlly之前调用System.exit
结束当前虚拟机,那么finally则不会得到执行:
1 | // 在fianlly之前调用 System.exit 结束当前虚拟机 |
throw & throws
throw用于主动抛出异常:
1 | public double divide(double x, double y) { |
加了throws的函数,函数内部抛出的异常要在函数外捕捉到:
1 | // 当抛出异常时,不在函数内捕捉,而是抛出到函数外 |
迭代器
1 | HashSet<Integer> set = new HashSet<>(); |
ArrayList 与 LinkedList 的区别
底层数据结构
ArrayList 使用动态数组来存储元素,这意味着在内存中分配一块连续的内存空间来保存元素
LinkedList 使用双向链表来存储元素,每个元素都包含对前一个和后一个元素的引用
插入和删除操作
ArrayList 的随机访问非常快速,因为可以通过索引直接访问元素。但是,插入和删除元素时,需要移动后续元素,效率较低
LinkedList 的插入和删除操作效率较高,因为只需更改节点的引用。但是,随机访问元素效率较低,因为必须从头或尾部开始遍历链表
内存消耗
ArrayList 在存储大量元素时可能会浪费一些内存,因为它分配一块较大的内存空间。但它在随机访问时效率较高
LinkedList 每个元素都需要额外的内存来存储引用,因此在存储大量元素时可能会消耗更多内存。但它在插入和删除操作时效率较高
适用场景
ArrayList 适用于需要频繁随机访问元素的情况,但不需要频繁执行插入和删除操作的情况
LinkedList 适用于需要频繁执行插入和删除操作的情况,但不需要频繁随机访问元素的情况
String相关
详见Java中的String。
泛型
泛型的优点:
- 类型安全:泛型在编译时提供了类型检查,可以在编译阶段捕获类型错误,而不是在运行时抛出异常
- 更好的性能:泛型的类型检查是在编译时进行的,不需要运行时的类型检查,因此可以提高程序的性能
- 代码复用:泛型可以编写更通用、可复用的代码,减少代码的冗余
- 可读性:使用泛型可以在代码中看到操作的数据类型,提高代码的可读性
泛型擦除:泛型信息在编译后会被擦除,在运行时,所有的泛型类型参数都会被视为Object
类型
线程
继承 Thread 类
自定义一个类继承Thread
,重写其run
方法,实例化后调用其start
方法开启线程:
1 | /// MyThread.java |
运行结果可能是先A后B,也可能是先B后A。
实现 Runnable 接口
创建自定义类实现Runnable
接口,重写其run
方法。创建一个Thread
对象,传入的参数即自定义类的一个实例,再调用Thread
对象的start
方法:
1 | /// MyRunnable.java |
Callable
创建自定义类实现Callable
接口,重写call
方法,即子线程要实现的逻辑,且有一个泛型返回值。使用FutureTask
类来包装Callable对象并启动线程,主线程将会等待子线程结束后,通过FutureTask对象的get
方法获取其返回值,然后才会往下执行。
1 | /// MyCallable.java |
输出结果:我是线程E
在主线程开始实例化Callable
之后,在主线程结束
之前。
LocalDateTime & LocalDate & LocalTime
参考的是这篇文章
三者区别是,LocalDate只能存日期,LocalTime只能存时间,LocalDateTime既可以存日期又可以存时间。这里只介绍LocalDateTime。
1 | // 实例化 |
Date & Calendar (已弃用)
看完一问chatGPT,才知道这俩已经被LocalDateTime取代了,旧教程害人啊……笔记都做完了,就不删了吧
按自定义格式输出时间:
1 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E"); |
其中HH:mm:ss是24小时制,hh:mm:ss是12小时制
或者用printf:
1 | System.out.printf("现在是:%tY-%tm-%td,%tp%tH:%tM:%tS,%tA", date, date, date, date, date, date, date, date); |
使用Calendar
1 | Calendar calendar = Calendar.getInstance(); // 创建对象,默认为当前时间 |
有关Date类与Calendar类的更多信息,参考这里