JDK 20
已于2023年3月21日
正式发布。它包含了 7 个JEP
,其中包括来自Amber
、Loom
和Panama
项目的新特性。例如,JEP 432:记录模式(Record Patterns,第二轮预览),JEP 433: switch 的模式匹配(Pattern Matching for switch,第四轮预览),JEP 434:外部函数与内存 API(Foreign Function & Memory API,第二轮预览)等等。
这些新特性如下:
JEP 429
:作用域值(Scoped Values,孵化阶段):支持在线程内和跨线程共享不可变数据。
JEP 432
:记录模式(Record Patterns,第二轮预览):允许您解构记录值,以实现对语言的增强。
JEP 433
: switch 的模式匹配(Pattern Matching for switch,第四轮预览):通过将模式匹配扩展到 switch,可以针对多个模式测试表达式,每个模式都有特定的操作。
JEP 434
:外部函数与内存 API(Foreign Function & Memory API,第二轮预览):允许 Java 程序更容易地与 Java 运行时之外的代码和数据进行互操作。
JEP 436
:虚拟线程(Virtual Threads,第二轮预览):引入了虚拟线程,这是一种轻量级线程,可以极大地减少编写、维护和观测高吞吐量并发应用程序的工作量。
JEP 437
:结构化并发(Structured Concurrency,第二轮孵化):通过将运行于不同线程中的多个任务视为一个工作单元,简化多线程编程。
JEP 438
:Vector API(第五轮孵化):允许以一种在运行时,可靠地编译为支持的 CPU 架构上的向量指令方式表达向量计算,从而实现优于等效标量计算的性能。
这些新特性旨在提高开发人员的工作效率,并优化 Java 语言和平台。它们提供了更多的语言改进、更好的并发支持、更好的与本地代码的互操作性等等。
这是一些 JDK 20 新特性的示例:
JEP 429: 引入了作用域值,它允许在线程内和跨线程共享不可变数据。这些数据优先于线程局部变量,尤其是在使用大量虚拟线程时。下面是一个简单的示例,演示如何使用作用域值:
import java.lang.invoke.ScopeVarHandle;
import java.lang.invoke.VarHandle;
class Example {
private static final VarHandle scopeVar = ScopeVarHandle.allocate(int.class);
public static void main(String[] args) {
try (var scope = ScopeVarHandle.open()) {
scopeVar.set(scope, 42);
new Thread(() -> {
try (var threadScope = ScopeVarHandle.open()) {
System.out.println(scopeVar.get(threadScope)); // prints 42
}
}).start();
}
}
}
在上面的示例中,我们使用ScopeVarHandle.allocate
方法为整数类型分配了一个作用域变量。然后,我们使用ScopeVarHandle.open
方法打开一个新的作用域,并使用set
方法设置作用域变量的值。在新线程中,我们再次打开一个新的作用域,并使用get
方法获取作用域变量的值。由于作用域变量在线程间共享,因此新线程中获取的值与主线程中设置的值相同。
**JEP 432: **记录模式(第二预览版): 记录模式允许您解构记录值,以实现对语言的增强。例如,假设您有一个记录类Person
,它有两个字段name
和age
。您可以使用记录模式在 switch 表达式中解构 Person 对象,如下所示:
Person person = new Person("John Doe", 42);
String message = switch (person) {
case Person(String name, int age) -> "Name: " + name + ", Age: " + age;
default -> "Unknown person";
};
JEP 433: Switch 模式匹配(第四预览版): 此 JEP 通过将模式匹配扩展到 switch,可以针对多个模式测试表达式,每个模式都有特定的操作。例如,假设您有一个对象obj
,它可以是整数、字符串或其他类型。您可以使用 switch 模式匹配来检查其类型并执行相应的操作,如下所示:
String message = switch (obj) {
case Integer i -> "Integer: " + i;
case String s -> "String: " + s;
default -> "Unknown type";
};
JEP 434: 外部函数和内存 API(第二预览版): 此 JEP 允许 Java 程序更容易地与 Java 运行时之外的代码和数据进行互操作。例如,您可以使用外部函数和内存 API 调用 C 库中的函数,如下所示:
MethodHandle strlen = CLinker.getInstance().downcallHandle(
LibraryLookup.ofDefault().lookup("strlen").get(),
MethodType.methodType(long.class, MemoryAddress.class),
FunctionDescriptor.of(CLinker.C_LONG, CLinker.C_POINTER)
);
long length = (long) strlen.invokeExact(CLinker.toCString("Hello").address());
JEP 436: 虚拟线程(第二预览版): 此 JEP 引入了虚拟线程,这是一种轻量级线程,可以极大地减少编写、维护和观测高吞吐量并发应用程序的工作量。例如,您可以使用虚拟线程执行并发任务,如下所示:
Thread.startVirtualThread(() -> {
// Task to be executed concurrently
});
JEP 437: 结构化并发(二次孵化阶段): 此 JEP 通过将运行于不同线程中的多个任务视为一个工作单元,简化多线程编程。例如,您可以使用结构化并发来执行多个并发任务并等待它们完成,如下所示:
try (StructuredTaskScope scope = new StructuredTaskScope()) {
scope.schedule(() -> {
// Task to be executed concurrently
});
scope.schedule(() -> {
// Another task to be executed concurrently
});
}
JEP 438: 矢量 API(五次孵化阶段): 此 JEP 允许以一种在运行时,可靠地编译为支持的 CPU 架构上的向量指令方式表达向量计算,从而实现优于等效标量计算的性能。例如,您可以使用矢量 API 执行向量加法,如下所示:
var a = IntVector.fromArray(IntVector.SPECIES_256, arrayA, 0);
var b = IntVector.fromArray(IntVector.SPECIES_256, arrayB, 0);
var c = a.add(b);
c.intoArray(arrayC, 0);