Java 14中的新功能
1. 概述
根据 Java 的新发布节奏, Java 14 于 2020 年 3 月 17 日发布,比上一版本 晚了整整六个月。 在本教程中,我们将查看该语言版本 14 的新功能和弃用功能的摘要。 我们还有更多关于 Java 14 的 详细文章 ,深入介绍了新功能。
2. 从早期版本继承的特性
Java 14 从以前的版本继承了一些特性。让我们一一看看。
2.1. 开关表达式(JEP 361 )
这些在 JDK 12 中首次作为预览功能引入,即使在 Java 13 中,它们也仅作为预览功能继续存在。但是现在,switch 表达式 已经标准化,因此它们是开发工具包的重要组成部分。
这实际上意味着此功能现在可以在生产代码中使用,而不仅仅是在开发人员试验的预览模式中使用。 作为一个简单的例子,让我们考虑一个场景,我们将一周中的几天指定为工作日或周末。 在此增强之前,我们将其编写为:
boolean isTodayHoliday;
switch (day) {
case "MONDAY":
case "TUESDAY":
case "WEDNESDAY":
case "THURSDAY":
case "FRIDAY":
isTodayHoliday = false;
break;
case "SATURDAY":
case "SUNDAY":
isTodayHoliday = true;
break;
default:
throw new IllegalArgumentException("What's a " + day);
}
使用 switch 表达式,我们可以更简洁地编写相同的内容:
boolean isTodayHoliday = switch (day) {
case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> false;
case "SATURDAY", "SUNDAY" -> true;
default -> throw new IllegalArgumentException("What's a " + day);
};
2.2. 文本块 ( JEP 368 )
文本块 继续其获得主流升级的旅程,并且仍可作为预览功能使用。
除了 JDK 13 使多行字符串更易于使用的功能外,在他们的第二个预览中,文本块现在有两个新的转义序列:
- : 表示行尾,这样就不会引入换行符
- \s:表示一个空格
例如:
String multiline = "A quick brown fox jumps over a lazy dog; the lazy dog howls loudly.";
现在可以写成:
String multiline = """
A quick brown fox jumps over a lazy dog; \
the lazy dog howls loudly.""";
这提高了句子对人眼的可读性,但不会在dog 之后添加新行;
3. 新的预览功能
3.1. instanceof的模式匹配(JEP 305 )
JDK 14 为instanceof 引入了模式匹配,旨在消除样板代码并让开发人员的工作变得更轻松。
为了理解这一点,让我们考虑一个简单的例子。 在此功能之前,我们写道:
if (obj instanceof String) {
String str = (String) obj;
int len = str.length();
// ...
}
现在,我们不需要那么多代码来开始使用obj作为 String:
if (obj instanceof String str) {
int len = str.length();
// ...
}
在未来的版本中,**Java 将为其他结构(例如*开关)***提供模式匹配。
3.2. 记录 ( JEP 359 )
引入记录 是为了减少数据模型 POJO 中的重复样板代码。它们简化了日常开发,提高了效率并大大降低了人为错误的风险。 例如, 具有id和password的User的数据模型可以简单地定义为:
public record User(int id, String password) { };
正如我们所看到的,我们在这里使用了一个新的关键字record。这个简单的声明会自动为我们添加构造函数、getters、equals、hashCode和toString方法。 让我们看看 JUnit 的实际效果:
private User user1 = new User(0, "UserOne");
@Test
public void givenRecord_whenObjInitialized_thenValuesCanBeFetchedWithGetters() {
assertEquals(0, user1.id());
assertEquals("UserOne", user1.password());
}
@Test
public void whenRecord_thenEqualsImplemented() {
User user2 = user1;
assertTrue(user1, user2);
}
@Test
public void whenRecord_thenToStringImplemented() {
assertTrue(user1.toString().contains("UserOne"));
}
4. 新制作特色
除了两个新的预览功能外,Java 14 还发布了一个具体的生产就绪功能。
4.1. 有用的 NullPointerExceptions ( JEP 358 )
以前, NullPointerException的堆栈跟踪没有太多可讲的故事,除了给定文件中给定行的某些值为空。 虽然有用,但此信息仅建议一行进行调试,而不是为开发人员描绘整个画面,仅通过查看日志即可理解。 现在 Java通过添加指出给定代码行中究竟什么是null的功能 使这变得更容易。 例如,考虑这个简单的片段:
int[] arr = null;
arr[0] = 1;
早些时候,在运行这段代码时,日志会说:
Exception in thread "main" java.lang.NullPointerException
at com.blogdemo.MyClass.main(MyClass.java:27)
但是现在,给定相同的场景,日志可能会说:
java.lang.NullPointerException: Cannot store to int array because "a" is null
如我们所见,现在我们准确地知道是哪个变量导致了异常。
5. 孵化功能
这些是 Java 团队提出的非最终 API 和工具,并提供给我们进行实验。它们与预览功能不同,在包jdk.incubator中作为单独的模块提供。
5.1. 外部内存访问 API ( JEP 370 )
这是一个新的 API ,允许 Java 程序以安全高效的方式访问堆外的外部内存,例如本机内存。 许多 Java 库(例如mapDB 和memcached) 确实会访问外部内存,现在是 Java API 本身提供更清洁的解决方案的时候了。带着这个意图,团队想出了这个 JEP 作为其现有的访问非堆内存的方法的替代方案——ByteBuffer API和sun.misc.Unsafe API。 该 API建立在MemorySegment、MemoryAddress和MemoryLayout的三个主要抽象之上,是访问堆内存和非堆内存的安全方式。
5.2. 打包工具 ( JEP 343 )
传统上,为了交付 Java 代码,应用程序开发人员只需发送一个 JAR 文件,用户应该在他们自己的 JVM 中运行该文件。 但是,用户更希望有一个安装程序,他们会双击以在其本机平台(例如 Windows 或 macOS)上安装程序包。 这个 JEP 旨在做到这一点。开发人员可以使用*<jlink>将 JDK 压缩为所需的最少模块,然后使用此打包工具创建一个轻量级映像,该映像可以在 Windows 上安装为 exe,在macOS 上安装为dmg* 。
6. JVM/HotSpot 特性
6.1. Windows ( JEP 365 ) 和 macOS ( JEP 364 ) 上的 ZGC – 实验性
Z Garbage Collector 是一种可扩展、低延迟的垃圾收集器,作为一项实验性功能首次在 Java 11 中引入。但最初,唯一受支持的平台是 Linux/x64。
在收到关于 ZGC for Linux 的积极反馈后,Java 14 也将其支持移植到了 Windows 和 macOS。虽然仍是一项实验性功能,但它已准备好在下一个 JDK 版本 中投入生产。
6.2. G1 的 NUMA 感知内存分配 ( JEP 345 )
与并行收集器不同,到目前为止,G1 垃圾收集器尚未实现非统一内存访问 (NUMA)。 看看它为跨多个套接字运行单个 JVM 提供的性能改进,引入这个 JEP 是为了让 G1 收集器也支持 NUMA。 目前,还没有计划将其复制到其他 HotSpot 收集器。
6.3. JFR 事件流(JEP 349 )
通过此增强功能,JDK 的飞行记录器数据现已公开,以便对其进行持续监控。这涉及对包jdk.jfr.consumer的修改,以便用户现在可以直接读取或流式传输记录数据。
7. 弃用或删除的功能
Java 14 弃用了一些特性:
- Solaris 和 SPARC Ports ( JEP 362 )——因为这个 Unix 操作系统和 RISC 处理器在过去几年里没有积极开发
- ParallelScavenge + SerialOld GC 组合(JEP 366 )——因为这是一种很少使用的 GC 算法组合,并且需要大量维护工作 还有一些删除:
- Concurrent Mark Sweep (CMS) Garbage Collector ( JEP 363 ) – 已被 Java 9 弃用,此 GC 已由 G1 继承为默认 GC。此外,现在还有其他性能更高的替代品可供使用,例如 ZGC 和 Shenandoah,因此删除了
- Pack200 工具和 API ( JEP 367 )——这些在 Java 11 中被弃用并被移除,现在被移除