JDK 新特性

137 阅读10分钟

一.JDK 新特性 JDK9 新特性(2017 年 9 月) 模块化 提供了 List.of()、Set.of()、Map.of()和 Map.ofEntries()等工厂方法 接口支持私有方法 Optional 类改进 多版本兼容 Jar 包 JShell 工具 try-with-resources 的改进 Stream API 的改进 设置 G1 为 JVM 默认垃圾收集器 支持 http2.0 和 websocket 的 API 重要特性:主要是 API 的优化,如支持 HTTP2 的 Client API、JVM 采用 G1 为默认垃圾收集器。

JDK10 新特性(2018 年 3 月) 局部变量类型推断,类似 JS 可以通过 var 来修饰局部变量,编译之后会推断出值的真实类型 不可变集合的改进 并行全垃圾回收器 G1,来优化 G1 的延迟 线程本地握手,允许在不执行全局 VM 安全点的情况下执行线程回调,可以停止单个线程,而不需要停止所有线程或不停止线程 Optional 新增 orElseThrow()方法 类数据共享 Unicode 语言标签扩展 根证书 重要特性:通过 var 关键字实现局部变量类型推断,使 Java 语言变成弱类型语言、JVM 的 G1 垃圾回收由单线程改成多线程并行处理,降低 G1 的停顿时间。

JDK11 新特性(2018 年 9 月)(LTS 版本) 增加一些字符串处理方法 用于 Lambda 参数的局部变量语法 Http Client 重写,支持 HTTP/1.1 和 HTTP/2 ,也支持 websockets 可运行单一 Java 源码文件,如:java Test.java ZGC:可伸缩低延迟垃圾收集器,ZGC 可以看做是 G1 之上更细粒度的内存管理策略。由于内存的不断分配回收会产生大量的内存碎片空间,因此需要整理策略防止内存空间碎片化,在整理期间需要将对于内存引用的线程逻辑暂停,这个过程被称为"Stop the world"。只有当整理完成后,线程逻辑才可以继续运行。(并行回收) 支持 TLS 1.3 协议 Flight Recorder(飞行记录器),基于 OS、JVM 和 JDK 的事件产生的数据收集框架 对 Stream、Optional、集合 API 进行增强 重要特性:对于 JDK9 和 JDK10 的完善,主要是对于 Stream、集合等 API 的增强、新增 ZGC 垃圾收集器。

JDK12 新特性(2019 年 3 月) Switch 表达式扩展,可以有返回值 新增 NumberFormat 对复杂数字的格式化 字符串支持 transform、indent 操作 新增方法 Files.mismatch(Path, Path) Teeing Collector 支持 unicode 11 Shenandoah GC,新增的 GC 算法 G1 收集器的优化,将 GC 的垃圾分为强制部分和可选部分,强制部分会被回收,可选部分可能不会被回收,提高 GC 的效率 重要特性:switch 表达式语法扩展、G1 收集器优化、新增 Shenandoah GC 垃圾回收算法。

JDK13 新特性(2019 年 9 月) Switch 表达式扩展,switch 表达式增加 yield 关键字用于返回结果,作用类似于 return,如果没有返回结果则使用 break 文本块升级 “”" ,引入了文本块,可以使用"""三个双引号表示文本块,文本块内部就不需要使用换行的转义字符 SocketAPI 重构,Socket 的底层实现优化,引入了 NIO FileSystems.newFileSystem 新方法 ZGC 优化,增强 ZGC 释放未使用内存,将标记长时间空闲的堆内存空间返还给操作系统,保证堆大小不会小于配置的最小堆内存大小,如果堆最大和最小内存大小设置一样,则不会释放内存还给操作系统 重要特性:ZGC 优化,释放内存还给操作系统、socket 底层实现引入 NIO。

JDK14 新特性(2020 年 3 月) instanceof 模式匹配,instanceof 类型匹配语法简化,可以直接给对象赋值,如 if(obj instanceof String str),如果 obj 是字符串类型则直接赋值给了 str 变量 引入 Record 类型,类似于 Lombok 的@Data 注解,可以向 Lombok 一样自动生成构造器、equals、getter 等方法; Switch 表达式-标准化 改进 NullPointerExceptions 提示信息,打印具体哪个方法抛的空指针异常,避免同一行代码多个函数调用时无法判断具体是哪个函数抛异常的困扰,方便异常排查; 删除 CMS 垃圾回收器 JDK15 新特性(2020 年 9 月) EdDSA 数字签名算法 Sealed Classes(封闭类,预览),通过 sealed 关键字修饰抽象类限定只允许指定的子类才可以实现或继承抽象类,避免抽象类被滥用 Hidden Classes(隐藏类) 移除 Nashorn JavaScript 引擎 改进 java.net.DatagramSocket 和 java.net.MulticastSocket 底层实现 JDK16 新特性(2021 年 3 月) 允许在 JDK C ++源代码中使用 C ++ 14 功能 ZGC 性能优化,去掉 ZGC 线程堆栈处理从安全点到并发阶段 增加 Unix 域套接字通道 弹性元空间能力 提供用于打包独立 Java 应用程序的 jpackage 工具 JDK16 相当于是将 JDK14、JDK15 的一些特性进行了正式引入,如 instanceof 模式匹配(Pattern matching)、record 的引入等最终到 JDK16 变成了 final 版本。

JDK17 新特性(2021 年 9 月)(LTS 版本) Free Java License JDK 17 将取代 JDK 11 成为下一个长期支持版本 Spring 6 和 Spring Boot 3 需要 JDK17 移除实验性的 AOT 和 JIT 编译器 恢复始终执行严格模式 (Always-Strict) 的浮点定义 正式引入密封类 sealed class,限制抽象类的实现 统一日志异步刷新,先将日志写入缓存,然后再异步刷新 虽然 JDK17 也是一个 LTS 版本,但是并没有像 JDK8 和 JDK11 一样引入比较突出的特性,主要是对前几个版本的整合和完善。

二.重要特性讲解 1.模块化 **模块化的目的,是让 jdk 的各个组件可以被分拆,复用和替换重写,**比如对 java 的 gui 不满意,可以自己实现一个 gui,对 java 的语法不满意,可以把 javac 替换成其他语言和其他语言的编译器,比如 kotlin 和 kotlinc 等,没有模块化,几乎很难实现,每次修改某个模块,总不能把整个 jdk 给重新编译一遍,再发布一个整个 sdk 吧,模块化可以帮助更有效的定制化和部署

2.变量类型推断 在 Java 10 中,提供了本地变量类型推断的功能,可以通过 var 声明变量:

var value = new MyObject(); 1 3.HTTP 客户端 API 作为 JDK11 中正式推出的新 Http 连接器,支持的功能还是比较新的,主要的特性有:

完整支持 HTTP 2.0 或者 HTTP 1.1 支持 HTTPS/TLS 有简单的阻塞使用方法 支持异步发送,异步时间通知 支持 WebSocket 支持响应式流 4.语法糖 Stream API 改进 Collectors.teeing() 1 teeing 收集器已公开为静态方法 Collectors::teeing。该收集器将其输入转发给其他两个收集器,然后将它们的结果使用函数合并

List list = Arrays.asList( new Student("唐一", 55), new Student("唐二", 60), new Student("唐三", 90));

//平均分 总分 String result = list.stream().collect(Collectors.teeing( Collectors.averagingInt(Student::getScore), Collectors.summingInt(Student::getScore), (s1, s2) -> s1 + ":" + s2));

//最低分 最高分 String result2 = list.stream().collect(Collectors.teeing( Collectors.minBy(Comparator.comparing(Student::getScore)), Collectors.maxBy(Comparator.comparing(Student::getScore)), (s1, s2) -> s1.orElseThrow() + ":" + s2.orElseThrow() ));

System.out.println(result); System.out.println(result2);

添加 Stream.toList 方法(jdk16)

List list = Arrays.asList("1", "2", "3"); //之前这样写 List oneList = list.stream() .map(Integer::parseInt) .collect(Collectors.toList()); //现在可以这样写 List twoList = list.stream() .map(Integer::parseInt) .toList();

Switch 表达式改进 支持箭头表达式(jdk12 预览 jdk14 标准)

此更改扩展了 switch 语句以便它可以用作语句或表达式。不必为 break 每个 case 块定义一个语句,我们可以简单地使用箭头语法。

boolean isWeekend = switch (day) { case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false; case SATURDAY, SUNDAY -> true; default -> throw new IllegalStateException("Illegal day entry :: " + day); };

int size = 3; String cn = switch (size) { case 1 -> "壹"; case 2 -> "贰"; case 3, 4 -> "叁"; default -> "未知"; }; System.out.println(cn);

yield 关键字(jdk13) 使用 yield,我们现在可以有效地从 switch 表达式返回值,并能够更容易实现策略模式。

return:在程序函数中返回某个值,返回之后函数不在继续执行,彻底结束。

yield: 带有yield的函数是一个迭代器,函数返回某个值时,会停留在某个位置,返回函数值后,会在前面停留的位置继续执行,直到程序结束

public class SwitchTest { public static void main(String[] args) { var me = 4; var operation = "平方"; var result = switch (operation) { case "加倍" -> { yield me * 2; } case "平方" -> { yield me * me; } default -> me; };

    System.out.println(result);
}

}

例子:

def foo(): print("starting...") while True: res = yield 4 print("res:",res) g = foo() print(next(g)) print("*"*20) print(next(g))

starting... 4 ******************** res: None 4 1 2 3 4 5 1.程序开始执行以后,因为foo函数中有yield关键字,所以foo函数并不会真的执行,而是先得到一个生成器g(相当于一个对象)

2.直到调用next方法,foo函数正式开始执行,先执行foo函数中的print方法,然后进入while循环

3.程序遇到yield关键字,然后把yield想想成return,return了一个4之后,程序停止,并没有执行赋值给res操作,此时next(g)语句执行完成,所以输出的前两行(第一个是while上面的print的结果,第二个是return出的结果)是执行print(next(g))的结果,

4.程序执行 print("*"20),输出 20 个

5.又开始执行下面的print(next(g)),这个时候和上面那个差不多,不过不同的是,这个时候是从刚才那个next程序停止的地方开始执行的,也就是要执行res的赋值操作,这时候要注意,这个时候赋值操作的右边是没有值的(因为刚才那个是return出去了,并没有给赋值操作的左边传参数),所以这个时候res赋值是None,所以接着下面的输出就是res:None,

6.程序会继续在while里执行,又一次碰到yield,这个时候同样return 出4,然后程序停止,print函数输出的4就是这次return出的4.

字符串 文本块改进(jdk13)

早些时候,为了在我们的代码中嵌入 JSON,我们将其声明为字符串文字:

String json = "{\r\n" + ""name" : "lingli",\r\n" + ""website" : "www.alibaba.com/\"\r\n" + "}"; 1 现在让我们使用字符串文本块编写相同的 JSON :

String json = """ { "name" : "Baeldung", "website" : "www.alibaba.com/" } """; 1 2 3 4 很明显,不需要转义双引号或添加回车。通过使用文本块,嵌入的 JSON 更易于编写,更易于阅读和维护。

5.JVM JDK9: 设置 G1 为 JVM 默认垃圾收集器

JDK10:并行全垃圾回收器 G1,通过并行 Full GC, 改善 G1 的延迟。目前对 G1 的 full GC 的实现采用了单线程-清除-压缩算法。JDK10 开始使用并行化-清除-压缩算法。

JDK11:推出 ZGC 新一代垃圾回收器(实验性),目标是 GC 暂停时间不会超过 10ms,既能处理几百兆的小堆,也能处理几个 T 的大堆。

JDK14 :删除 CMS 垃圾回收器;弃用 ParallelScavenge + SerialOld GC 的垃圾回收算法组合;将 zgc 垃圾回收器移植到 macOS 和 windows 平台

JDk 15 : ZGC (JEP 377) 和Shenandoah (JEP 379) 不再是实验性功能。默认的 GC 仍然是G1。

JDK16:增强 ZGC,ZGC 获得了 46 个增强功能 和 25 个错误修复,控制 stw 时间不超过 10 毫秒