jdk 14 主要的新特性参考:
openjdk JDK 14
baeldung New Features in Java 14
JDK 14 的新特性
Java 14 于2020年3月17日发布,包含新特性:
- 305: Pattern Matching for instanceof (Preview)
- 343: Packaging Tool (Incubator)
- 345: NUMA-Aware Memory Allocation for G1
- 349: JFR Event Streaming
- 352: Non-Volatile Mapped Byte Buffers
- 358: Helpful NullPointerExceptions
- 359: Records (Preview)
- 361: Switch Expressions (Standard)
- 362: Deprecate the Solaris and SPARC Ports
- 363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector
- 364: ZGC on macOS
- 365: ZGC on Windows
- 366: Deprecate the ParallelScavenge + SerialOld GC Combination
- 367: Remove the Pack200 Tools and API
- 368: Text Blocks (Second Preview)
- 370: Foreign-Memory Access API (Incubator)
早期版本实验特性
Switch Expressions (JEP 361)
switch 表达式终于成为正式特性了,从JDK12引入,JDK13迭代,终于成为了标准的特性了。
这意味着switch 表达式可以用在生产环境了,而不是仅仅在预览模式下由开发来试试。
还是上次那个例子,判断是否是节假日,之前的写法:
1 | boolean isTodayHoliday; |
如今可以使用switch 表达式,更简介明了(注意直接赋值)
1 | boolean isTodayHoliday = switch (day) { |
掌握吧,已经可以直接用了。
Text Blocks (JEP 368)
好消息是第二个版本了,坏消息是依然是预览特性。这个版本新增了两个转意:
\: 代表行还没有结束\s: 代表一个空字符
例子
1 | String multiline = "A quick brown fox jumps over a lazy dog; the lazy dog howls loudly."; |
现在可以写成这样
1 | String multiline = """ |
只是让语句变的更可读,并没有在 dog后面加入一个新行。(这就是各类命令行常用的啊)
新的实验特性
Pattern Matching for instanceof (JEP 305)
jdk 14 中新增了 instanceof的模式匹配特性,来让程序员的人生在轻松那么一些。
ps. 我记得我在jdk12中提到过这一特性,又确认了一下,应该是当时搞错了,这个特性确认是在 jdk14中才加入的。出错的出处也找到了,是这里搞错了 。
另外该特性是在 JDK 16 中正式发布的
有多轻松呢?这么轻松:
1 | Object obj = "Hello World!"; |
现在我们可以这么写
1 | if (obj instanceof String str) { |
看一眼可以了,预览特性。
Records (JEP 359)
引入Records 可以帮助我们减少不可变数据模型中一堆无意义的重复的模板代码。我觉得 JEP 359中的Motivation and Goals写的很清楚,大意就是:
都说java太啰嗦太多规范限定,写一个数据载体模型需要写一堆无意义的 get/set/equals/hashcode/toString 等方法,虽然IDE会帮忙处理这些重复的代码,
但是无法帮助代码阅读的人在一堆代码里面提取出 这个类只是一个数据的载体 这样的结论。写一个java数据模型应该是简单的:简单写,简单读,简单的判断是否有错误。
例子,定一个 User 模型,包含 id 和 password 属性。
1 | public record User(int id, String password) { } |
使用
1 | private User user = new User(0, "UserOne"); |
可以看见对 id/password 的获取不是用 getXxx了,而是直接用数据名同名的方法名。没有set因为是不可变数据类型。
record 还可以覆盖改造方法、创建静态类、定义自己的方法
1 | public record User(int id, String password) { |
总结下,感觉就是lombok的@Data,加了数据不可变的限制。
新的正式特性
Helpful NullPointerExceptions (JEP 358)
以前NullPointerException的异常栈并没有包含多少信息来告诉我们到底哪里NPE了,只告诉了我们异常的类以及对应的代码行。
现在Java 14增加了直接指出哪里NPE的能力,比如:
1 | int[] arr = null; |
如果在以前
1 | Exception in thread "main" java.lang.NullPointerException |
而现在的报错是这样子的
1 | java.lang.NullPointerException: Cannot store to int array because "a" is null |
我们可以准确的知道哪一个字段导致了NPE。
我们在用刚才那个Record试一下:
1 |
|
输出
1 | java.lang.NullPointerException: Cannot invoke "String.toUpperCase()" because the return value of "com.forg.java14.pojo.User.password()" is null |
很明确的就指出了哪个字段是null,舒服~
孵化中的特性
孵化中的特性不同于预览特性,都单独放在了独立模块的jdk.incubator包下面
Foreign Memory Access API (JEP 370)
Java需要访问堆内存之外的内存空间是,通常有两种方法:
- java.nio.ByteBuffer
- sun.misc.Unsafe
java.nio.ByteBuffer允许使用allocateDirect()方法在堆内存之外分配内存空间。但是 ByteBuffer 大小不能超过2G,释放内存需要依赖垃圾回收器。sun.misc.Unsafe 的使用是不安全的,可能会造成JMV崩溃,另外Unsafe 并不推荐使用。
JEP 370 引入了一套高效的API来访问外部内存地址,目前还是在孵化阶段,相关API在jdk.incubator.foreign模块的jdk.incubator.foreign包中。
该API包含三个核心接口: MemorySegment、MemoryAddress和MemoryLayout。
MemorySegment接口表示一个连续的内存区域,它有空间上和时间上的约束:空间上的约束指的是不能访问所分配内存空间之外的地址;时间上的约束指的是当MemorySegment被关闭之后,不能继续对它进行操作。关闭一个MemorySegment会释放内存。MemoryAddress接口描述在MemorySegment中的相对位置。通常是用法是通过MemorySegment.baseAddress()方法得到起始地址,再使用offset(long l)方法移到到新的地址。MemoryLayout接口描述MemorySegment中的内存布局。布局的最小单元有两种:表示单个值的ValueLayout,顺序布局SequenceLayout。
Packaging Tool (JEP 343)
通常java交付只需要给到对应的jar文件,然后在自己的JVM中运行,但是大部分人希望通过双击安装来在自己的平台上,就比如 windows和 macOS 。
JEP 343 就是这个目的,开发者可以使用 jlink 来把最小化依赖的JDK模块压缩打包,然后创建一个轻量化的镜像,比如windows系统的exe,macOS的dmg 。
JVM/HotSpot 特性
ZGC on Windows (JEP 365) and macOS (JEP 364) – Experimental
早在java 11引入的实验性的ZGC一直都只支持 Linux/x64 平台。
在java 14中已经支持了Windows与macOS,虽然只是个实验性的特性,以后终将会在正式版本中发布的。
NUMA-Aware Memory Allocation for G1 (JEP 345)
不像并行回收器,G1垃圾回收器至今没有实现 Non-uniform memory access (NUMA) ,在这次JEP中增加G1的NUMA支持。
JFR Event Streaming (JEP 349)
通过这一增强,JDK的飞行记录器数据现在被公开,以便可以持续监控。这涉及到对包jdk.jfr.cosumer的修改,以便用户现在可以直接读取或流式传输记录数据。
弃用或者删除的特性
弃用的
- Solaris and SPARC Ports (JEP 362) – because this Unix operating system and RISC processor are not in active development since the past few years
- ParallelScavenge + SerialOld GC Combination (JEP 366) – since this is a rarely used combination of GC algorithms, and requires significant maintenance effort
删除的 - Concurrent Mark Sweep (CMS) Garbage Collector 在java 9 的时候已经被标记弃用,其代替者G1已经是默认的垃圾回收器了,而且还有其他很多可选的 ZGC,Shenandoah 。所以直接删除了。
- Pack200 Tools and API (JEP 367) – these were deprecated for removal in Java 11, and now removed
总结一下
正式特性有
- Switch Expressions
- Helpful NullPointerExceptions