JDK16特性
一、JAVA16概述
2021年3月16日正式发布,一共更新了17JEP
https://openjdk.java.net/projects/jdk/16/
二、语法层面变化
1.JEP 397:密封类(第二次预览)
- sealed class 第二次预览
通过密封的类和接口来增强Java编程语言,这是新的预览特性,用于限制超类的使用密封的类和接口限制其他可继承或者实现他们的其他类或接口.
- 目标
允许类或接口的开发者来控制那些代码负责实现,提供了比限制使用超类的访问修饰符声明方式更多选择,并通过支持对模式的详尽分析而支持模式匹配的未来发展
在java中,类层次构造通过集成实现代码的重用,父类的方法可以被许多子类继承.但是,类层次接口的目的并不总是重用代码.有时是对域中存在的各种可能性进行建模,例如图形库支持函的形状类型.当以这种方式使用类层次结构是,我们可能需要限制子类集从而简化建模.
虽然我们可以通过final来限定子类继承,但是这是绝对杜绝类子类,而类的密封是允许子类,但是限定是那个或者哪些.
2.JEP 394:instanceof 的模式匹配
- 概括
增强Java编程语言与模式匹配的 instanceof
运算符。 模式匹配 允许更简洁、更安全地表达程序中的常见逻辑,即从对象中有条件地提取组件。
- 历史
模式匹配 instanceof
由JEP 305提出 并在 JDK 14 中作为 预览功能提供。它由JEP 375重新提出, 并在 JDK 15 中进行第二轮预览。
该 JEP 建议在 JDK 16 中完成该功能,并进行以下改进:
- 取消模式变量是隐式 final 的限制,以减少局部变量和模式变量之间的不对称性。
- 将
instanceof
类型S的表达式与类型T的模式进行比较,使模式表达式成为编译时错误,其中S是T的子类型。(这个instanceof
表达式总是成功,然后毫无意义。相反的情况,模式匹配总是失败,已经是一个编译时错误。)
可以根据进一步的反馈合并其他改进。
- 原因
几乎每个程序都包含某种逻辑,这些逻辑结合了测试表达式是否具有特定类型或结构,然后有条件地提取其状态的组件以进行进一步处理。例如,所有 Java 程序员都熟悉 instanceof
-and-cast 习语:
if (obj instanceof String) {
String s = (String) obj;
...
}
有三件事情会在这里:测试(是 obj
一 String
?),转换(铸造 obj
到 String
),和一个新的局部变量的声明(s
),这样我们就可以使用字符串值。这种模式很简单,所有 Java 程序员都可以理解,但由于几个原因,它并不是最理想的。它很乏味;应该不需要同时进行类型测试和强制转换(instanceof
测试后你还会做什么 ?)。这个样板——特别是该类型的三个出现 String
——混淆了后面更重要的逻辑。但最重要的是,重复提供了错误潜入程序中的机会。
我们相信 Java 是时候拥抱模式匹配了,而不是寻求临时解决方案。模式匹配允许简洁地表达对象的所需“形状”(模式),并允许各种语句和表达式根据其输入(匹配)测试该“形状” 。许多语言,从 Haskell 到 C#,都因为其简洁和安全而采用了模式匹配
这允许我们将上面繁琐的代码重构为以下内容:
if (obj instanceof String s) {
// Let pattern matching do the work!
...
}
3.JEP 395:记录
- 概述
使用记录增强 Java 编程语言,记录是充当不可变数据的透明载体的类。记录可以被认为是名义元组。
- 历史
记录由JEP 359提出 并在JDK 14 中作为 预览功能提供。
作为对反馈的回应,JEP 384对该设计进行了改进, 并在JDK 15 中作为第二次预览功能交付 。第二次预览的改进如下:
- 在第一个预览版中,规范构造函数必须是
public
. 在第二个预览中,如果隐式声明了规范构造函数,则其访问修饰符与记录类相同;如果显式声明了规范构造函数,则其访问修饰符必须提供至少与记录类一样多的访问权限。@Override
注释的含义被扩展为包括注释方法是记录组件的显式声明的访问器方法的情况。- 为了强制使用紧凑构造函数,分配给构造函数主体中的任何实例字段会导致编译时错误。
- 引入了声明本地记录类、本地枚举类和本地接口的能力。
该 JEP 建议在 JDK 16 中完成该功能,并进行以下改进:
- 放宽长期存在的限制,即内部类不能声明显式或隐式静态成员。这将变得合法,特别是将允许内部类声明作为记录类的成员。
可以根据进一步的反馈合并其他改进。
- 目标
- 设计一个面向对象的构造来表达简单的值聚合。
- 帮助开发人员专注于建模不可变数据而不是可扩展行为。
- 自动实现数据驱动的方法,例如
equals
和访问器。- 保留长期存在的 Java 原则,例如名义类型和迁移兼容性。
- 细节实现
人们普遍抱怨“Java 太冗长”或“仪式太多”。一些最严重的违规者是那些只不过是少数值的不可变 数据载体 的类。正确编写这样的数据载体类涉及许多低价值、重复、容易出错的代码:构造函数、访问器、 equals
、hashCode
、toString
等。 例如,携带 x 和 y 坐标的类不可避免地以类似下面这样的方式结束:
class Point {
private final int x;
private final int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
int x() {
return x; }
int y() {
return y; }
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
Point other = (Point) o;
return other.x == x && other