Java 14中的新特性

2023/06/09

1. 概述

根据Java的新发布节奏,Java 14于2020年3月17日发布,比上一版本晚了整整六个月。

在本教程中,我们将查看该语言版本14的新功能和已弃用功能的摘要

我们还有关于Java 14的更详细的文章,提供了对新功能的深入介绍。

2. 从早期版本继承的特性

Java 14中的一些功能从以前的版本继承而来,让我们一一看看。

2.1 Switch表达式(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();
    // ...
}

现在,我们不需要那么多代码:

if (obj instanceof String str) {
    int len = str.length();
    // ...
}

在未来的版本中,Java将为其他构造(例如switch)提供模式匹配

3.2 Record(JEP 359)

引入记录是为了减少数据模型POJO中的重复样板代码,它们可以简化日常开发,提高了效率并大大降低了人为错误的风险

例如,具有id和password的用户的数据模型可以简单地定义为:

public record User(int id, String password) {
}

正如我们所看到的,我们在这里使用了一个新的关键字record。这个简单的声明会自动为我们添加构造函数、getters、equals、hashCode和toString方法。

下面是使用JUnit的一些简单测试:

private User user1 = new User(0, "UserOne");

@Test
void givenRecord_whenObjInitialized_thenValuesCanBeFetchedWithGetters() {
    assertEquals(0, user1.id());
    assertEquals("UserOne", user1.password());
}

@Test
void whenRecord_thenEqualsImplemented() {
    User user2 = user1;
    assertTrue(user1, user2);
}

@Test
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 cn.tuyucheng.taketoday.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库(例如mapDBmemcached)确实会访问外部内存,现在是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(ZGC)是一种可扩展、低延迟的垃圾收集器,作为一项实验性功能首次在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):这些工具和API在Java 11中被弃用,现在被移除

8. 总结

在本教程中,我们了解了Java 14的各种JEP。

总的来说,这个版本的Java语言有16个主要功能,包括预览功能、孵化器、弃用和删除。我们逐个介绍了所有这些,并通过示例查看了语言功能。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章