Java 14 特性
按照六个月的周期传统,在2019年9月17日发布了Java 13后,Java 14,另一个非LTS版本计划于2020年3月17日发布。
Java 14特性
以下是Java 14功能的列表:
- Switch Expressions (Standard) – JEP 361
- Pattern Matching for instanceof (Preview) – JEP 305
- Helpful NullPointerExceptions – JEP 358
- Records (Preview) – JEP 359
- Text Blocks (Second Preview) – JEP 368
- Packaging Tool (Incubator) – JEP 343
- NUMA-Aware Memory Allocation for G1 – JEP 345
- JFR Event Streaming – JEP 349
- Non-Volatile Mapped Byte Buffers – JEP 352
- ZGC on macOS – JEP 364
- ZGC on Windows – JEP 365
- Foreign-Memory Access API (Incubator) – JEP 370
在Mac OS上安装Java 14设置
- To get started with Java 14, download the JDK from here.
- Copy and extract the tar file in the /Library/Java/JavaVirtualMachines as shown below:
$ cd /Library/Java/JavaVirtualMachines
$ sudo cp ~/Downloads/openjdk-14_osx-x64_bin.tar.gz /Library/Java/JavaVirtualMachines
$ sudo tar xzf openjdk-14_osx-x64_bin.tar.gz
$ sudo rm openjdk-14_osx-x64_bin.tar.gz
完成上述步骤后,使用任何文本编辑器打开 bash_profile 文件。我使用的是 vim ~/.bash_profile。将 Java14 的路径设置为 JAVA_HOME,保存更改,并执行 source ~/.bash_profile 命令以反映更改。
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home
最后,您已准备好使用Java 14编译和运行程序。我们将使用JShell,这是一个交互式的REPL命令行工具,用于快速测试新的Java 14功能。
重要的是要注意,Java 14发布的许多功能都处于预览阶段。这意味着虽然它们现在可以完全使用,但以后可能会进行修改。有些功能可能会成为标准,或者在下一个发布周期中被移除。为了测试预览功能,您需要在运行JShell或Java程序时显式地设置–enable-preview,如下所示:
jshell --enable-preview
javac --release 14 --enable-preview Author.java
在接下来的几个部分中,让我们讨论一些语言和JVM的特性。
推荐阅读:在Linux上安装Java 14
1. 值交换表达式
在过去的两个版本中,即Java 12和Java 13中,Switch Expressions一直作为预览功能,现在它们已经在Java 14中获得了永久状态。
- Java 12 introduced the lambda syntax for switch expressions thereby allowing multiple case labels for pattern matching as well as preventing fall-throughs which lead to verbose code. It also enforced exhaustive cases wherein a compilation error would be thrown if all the input cases aren’t covered.
- Java 13, the second preview introduced yield statements instead of break for returning values from an expression.
Java 14终于将这些功能纳入了标准。
String result = switch (day) {
case "M", "W", "F" -> "MWF";
case "T", "TH", "S" -> "TTS";
default -> {
if(day.isEmpty())
yield "Please insert a valid day.";
else
yield "Looks like a Sunday.";
}
};
System.out.println(result);

注意:yield 不是 Java 中的新关键字,它只是在 switch 表达式中使用。
2. instanceof实例的模式匹配(预览)
请任何Java开发人员展示他们的代码库,你会看到代码中大量使用了instanceof条件。具体来说,一个instanceof条件检查通常会跟随一个类型转换。
Java 14通过使条件提取更加简洁,消除了这种冗长。
在Java 14之前:
if (obj instanceof Journaldev) {
Journaldev jd = (Journaldev) obj;
System.out.println(jd.getAuthor());
}
从Java 14开始:
if (obj instanceof Journaldev jd) {
System.out.println(jd.getAuthor());
}
在上述代码中,只有当obj属于Journaldev类型时,实例jd才会被赋值。变量的作用范围仅限于条件块内。
3. 有用的空指针异常 de
空指针异常对于任何开发者来说都是一个噩梦。在Java 13之前,调试臭名昭著的空指针异常是棘手的。开发者必须依赖其他调试工具或手动找出变量/方法是否为空,因为堆栈跟踪只会显示行号。
在Java 14之前:
String name = jd.getBlog().getAuthor()
//Stacktrace
Exception in thread "main" java.lang.NullPointerException
at NullPointerExample.main(NullPointerExample.java:5)
Java 14新引入了一项JVM功能,通过更详细的堆栈展示提供更好的洞察力。
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Blog.getAuthor()" because the return value of "Journaldev.getBlog()" is null
at NullPointerExample.main(NullPointerExample.java:4)
注意:上述功能并不是语言特性,而是运行环境的改进。
4. 记录(预览)
记录是一种存储纯数据的数据类。引入记录的想法是为了快速创建简单而简洁、没有样板代码的类。
通常情况下,Java中的一个类需要你实现equals()、hashCode()方法以及getter和setter方法。虽然一些集成开发环境支持自动生成这些类,但代码仍然冗长。而有了记录(record),你只需要按以下方式定义一个类。
record Author(){}
//or
record Author (String name, String topic) {}
Java 编译器将自动生成构造函数、私有的 final 字段、访问器、equals/hashCode 方法以及 toString 方法。上述类的自动生成 getter 方法是 name() 和 topic()。
在使用javac对程序编译后,您可以使用javap Author来查看生成的代码。下面的示例显示了生成的用于记录作者(String name,String topic){} 的类。

记录的语义与Kotlin中的数据类相似。
此外,我们可以按照以下方式向记录中添加额外的字段、方法和构造函数。
record Author (int id, String name, String topic) {
static int followers;
public static String followerCount() {
return "Followers are "+ followers;
}
public String description(){
return "Author "+ name + " writes on "+ topic;
}
public Author{
if (id < 0) {
throw new IllegalArgumentException( "id must be greater than 0.");
}
}
}
在记录中定义的附加构造函数被称为紧凑构造函数。它不包含任何参数,只是规范构造函数的扩展。
编译器不会单独生成紧凑构造函数,而是将其用于验证情况,并在主构造函数开始时调用。
关于Records需要注意的几个重要事项:
- A record can neither extend a class nor it can be extended by another class. It’s a final class.
- Records cannot be abstract
- Records cannot extend any other class and cannot define instance fields inside the body. Instance fields must be defined in the state description only
- Declared fields are private and final
- The body of a record allows static fields and methods
推荐阅读: Java Records
4.1) 记录中引用字段的值可以被改变。
需要注意的是,对于定义为对象的字段,只有引用是不可变的。底层的值可以被修改。下面的示例展示了一个记录,其中ArrayList被修改。正如你所看到的,只要ArrayList被改变,值就会被修改。

4.2)记录可以实现接口。
以下代码展示了使用记录实现接口的示例。
record Author(String name, String topic) implements Information {
public String getFullName() {
return "Author "+ name + " writes on " + topic;
}
}
interface Information {
String getFullName();
}
以下是在JShell中执行上述代码的输出结果:

4.3) 记录支持多个构造函数。
如下所示,记录允许声明带参数或不带参数的多个构造函数。
record Author(String name, String topic) {
public Author() {
this("NA", "NA");
}
public Author(String name) {
this(name, "NA");
}
}
4.4) 记录允许修改访问者方法
虽然记录会为状态描述中定义的字段生成公共访问器方法,但它们也允许您在正文中重新定义访问器方法,如下所示。
record Author(String name, String topic) {
public String name() {
return "This article was written by " + this.name;
}
}
4.5)运行时检查记录及其组件
记录为我们提供了isRecord()和getRecordComponents()来检查类是否是一个记录,以及查看它的字段和类型。以下示例展示了如何进行操作。

尽管在上述代码示例中我们确实添加了额外的字段和方法到记录中,但请确保不要过度使用。记录设计为纯数据载体,如果您希望实现大量额外的方法,最好还是使用普通类。
5. 文本块(预览版)
Java 13引入了文本块作为预览功能,旨在方便创建多行字符串字面量。它在简单创建HTML、JSON或SQL查询字符串方面非常有用。
在Java 14中,文本块仍处于预览状态,并引入了一些新的功能。现在我们可以使用:
- Backslash for displaying nice-looking multiline string blocks.
- \s is used to consider trailing spaces which are by default ignored by the compiler. It preserves all the spaces present before it.
String text = """
Did you know \
Java 14 \
has the most features among\
all non-LTS versions so far\
""";
String text2 = """
line1
line2 \s
line3
""";
String text3 = "line1\nline2 \nline3\n"
//text2 and text3 are equal.
参考资料:OpenJDK 14