JDk18~20新特性
JDK18 新特性
JDK18 于 2022 年 3 月发布,作为一个非长期支持版本(非 LTS)。
1. 简单 Web 服务器(Simple Web Server)
JDK 18 引入了一个简单的命令行 Web 服务器,旨在提供一个轻量级的 HTTP 文件服务器,方便开发和测试。该服务器主要用于快速启动一个简单的 Web 服务,而不需要安装复杂的 Web 服务器软件。
# 启动简单的 Web 服务器,默认为当前目录,端口 8000
$ jwebserver
# 自定义根目录和端口
$ jwebserver --directory /path/to/directory --port 8080
通过这种方式,你可以快速在本地启动一个 Web 服务器,便于测试静态内容或本地开发。
2. UTF-8 作为默认字符集(JEP 400)
JDK 18 将 UTF-8 设定为默认字符集(Charset),这意味着在不指定字符集的情况下,所有的字符编码和解码操作都会使用 UTF-8。这一变化提高了跨平台的一致性和兼容性。
// 以前可能会受到平台默认字符集的影响
String text = new String(byteArray, Charset.defaultCharset());
// JDK 18 中默认使用 UTF-8
String text = new String(byteArray); // 默认使用 UTF-8
3. switch 再次增强
JDK 18 引入了模式匹配 switch
的第二个预览版,这个特性扩展了 switch
语句,使其能够基于类型进行模式匹配,并且支持更多复杂的条件判断。
public class PatternMatchingSwitchExample {
public static void main(String[] args) {
Object obj = 123;
String result = switch (obj) {
case Integer i -> "Integer: " + i;
case String s -> "String: " + s;
default -> "Unknown type";
};
System.out.println(result); // 输出: Integer: 123
}
}
4. 外部函数和内存 API(第二次孵化)
外部函数和内存 API 提供了一个高效的方式来操作非堆内存和调用本地代码。在 JDK 18 中,该 API 进行了进一步的优化和增强。
import jdk.incubator.foreign.*;
public class ForeignMemoryExample {
public static void main(String[] args) {
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
MemoryAccess.setByteAtOffset(segment, 0, (byte) 42);
byte value = MemoryAccess.getByteAtOffset(segment, 0);
System.out.println("Value: " + value); // 输出: Value: 42
}
}
}
5. 重新实现核心反射(JEP 416)
JDK 18 重新实现了核心反射,优化了反射调用的性能和内存使用。新的实现基于方法句柄,使得反射调用更加高效。
import java.lang.reflect.*;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
Method method = String.class.getMethod("length");
String str = "Hello, World!";
int length = (int) method.invoke(str);
System.out.println("Length: " + length); // 输出: Length: 13
}
}
6. 向量 API(第三次孵化)
JDK 18 继续扩展了 Vector API,它允许开发者利用 SIMD(单指令多数据)指令编写高性能的向量化代码,从而提升计算密集型应用的性能。
import jdk.incubator.vector.*;
public class VectorExample {
public static void main(String[] args) {
var species = FloatVector.SPECIES_256;
var a = FloatVector.fromArray(species, new float[] {1, 2, 3, 4, 5, 6, 7, 8}, 0);
var b = FloatVector.fromArray(species, new float[] {8, 7, 6, 5, 4, 3, 2, 1}, 0);
var c = a.add(b);
float[] result = new float[species.length()];
c.intoArray(result, 0);
System.out.println(Arrays.toString(result)); // 输出: [9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0]
}
}
7. 增强的伪随机数生成器(JEP 356)
JDK 18 增强了伪随机数生成器的 API,引入了统一的接口,使得使用不同类型的伪随机数生成器更加灵活和方便。
import java.util.random.*;
public class RandomExample {
public static void main(String[] args) {
RandomGenerator random = RandomGenerator.of("L64X128MixRandom");
System.out.println(random.nextInt()); // 输出一个随机整数
}
}
8. JDK 进程 API(JEP 102)
JDK 18 对进程 API 进行了扩展,增加了对本地进程和环境信息的访问,增强了跨平台的进程管理能力。
import java.lang.ProcessHandle;
public class ProcessAPIExample {
public static void main(String[] args) {
ProcessHandle current = ProcessHandle.current();
long pid = current.pid();
System.out.println("Current PID: " + pid);
}
}
JDK19 新特性
JDK 19 于 2022 年 9 月发布,作为一个非长期支持版本(非 LTS)。
1. 虚拟线程(预览)
虚拟线程(Virtual Threads)是 JDK 19 中的一项重要改进,旨在大幅简化高并发应用的开发。这些线程是轻量级的,可以大规模创建而不会占用过多的系统资源。虚拟线程使得编写高并发代码更加简单,不再需要为每个任务管理复杂的线程池。
虚拟线程介绍
public class VirtualThreadExample {
public static void main(String[] args) throws InterruptedException {
Thread.startVirtualThread(() -> System.out.println("Hello from a virtual thread!"));
Thread.sleep(100); // 确保虚拟线程有机会运行
}
}
使用场景
- 高并发的 Web 服务器
- 并行数据处理
- 大量 I/O 操作的应用
2. switch
增加(第三次孵化)
模式匹配 for switch
语句在 JDK 19 中进行了进一步扩展,支持更复杂的条件判断和类型匹配。它允许开发者在 switch
语句中直接匹配对象类型,并将其转换为相应的类型变量,从而简化代码结构。
public class PatternMatchingSwitchExample {
public static void main(String[] args) {
Object obj = "Hello";
String result = switch (obj) {
case String s when s.length() > 5 -> "Long String";
case String s -> "Short String";
case Integer i -> "Integer: " + i;
default -> "Unknown type";
};
System.out.println(result); // 输出: Long String
}
}
3. 外部函数和内存 API(第三次孵化)
外部函数和内存 API 提供了一种安全、高效的方式来访问和操作非堆内存,并与本地代码进行交互。JDK 19 中,这些 API 进行了进一步优化,支持更多的内存操作和跨语言调用。
import jdk.incubator.foreign.*;
public class ForeignMemoryExample {
public static void main(String[] args) {
try (MemorySegment segment = MemorySegment.allocateNative(1024)) {
MemoryAccess.setByteAtOffset(segment, 0, (byte) 42);
byte value = MemoryAccess.getByteAtOffset(segment, 0);
System.out.println("Value: " + value); // 输出: Value: 42
}
}
}
使用场景
- 高性能的本地内存操作
- 调用本地库(如 C/C++)
4. 向量 API Vector API(第四次孵化)
Vector API 允许开发者利用现代 CPU 的 SIMD 指令进行向量化计算,从而提升数据密集型应用的性能。在 JDK 19 中,Vector API 进行了进一步优化,支持更多的操作和数据类型。
import jdk.incubator.vector.*;
public class VectorExample {
public static void main(String[] args) {
var species = FloatVector.SPECIES_256;
var a = FloatVector.fromArray(species, new float[] {1, 2, 3, 4, 5, 6, 7, 8}, 0);
var b = FloatVector.fromArray(species, new float[] {8, 7, 6, 5, 4, 3, 2, 1}, 0);
var c = a.add(b);
float[] result = new float[species.length()];
c.intoArray(result, 0);
System.out.println(Arrays.toString(result)); // 输出: [9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0]
}
}
使用场景
- 数值计算和科学计算
- 图形处理
- 数据分析
5. 结构化并发(孵化)
结构化并发,是一种多线程编程方法,目的是为了通过结构化并发 API 来简化多线程编程,并不是为了取代java.util.concurrent,目前处于孵化器阶段。
结构化并发将不同线程中运行的多个任务视为单个工作单元,从而简化错误处理、提高可靠性并增强可观察性。也就是说,结构化并发保留了单线程代码的可读性、可维护性和可观察性。结构化并发的基本 API 是 StructuredTaskScope。
StructuredTaskScope 支持将任务拆分为多个并发子任务,在它们自己的线程中执行,并且子任务必须在主任务继续之前完成。StructuredTaskScope 的基本用法如下:
try (var scope = new StructuredTaskScope<Object>()) {
Future<Integer> future1 = scope.fork(task1);
Future<String> future2 = scope.fork(task2);
// 等待线程完成
scope.join();
}
6. 外部函数和内存 API (第三次孵化)
Foreign Function & Memory API
提供了一种更简单和高效的方式来与本地代码进行交互。它允许开发者直接调用本地库,并且对内存进行高效的读写操作。
import jdk.incubator.foreign.*;
import java.lang.invoke.MethodHandles;
public class ForeignFunctionExample {
public static void main(String[] args) throws Throwable {
System.out.println("Calling native function...");
System.loadLibrary("example"); // 加载本地库
MethodHandle handle = CLinker.systemCLinker().downcallHandle(
SymbolLookup.loaderLookup().lookup("nativeFunction").orElseThrow(),
FunctionDescriptor.of(CLinker.C_INT)
);
int result = (int) handle.invokeExact();
System.out.println("Result from native function: " + result);
}
}
JDK20 新特性
JDK 20 是一个非长期支持版本(非 LTS),于 2023 年 3 月发布。
1. 虚拟线程(第二次预览)
JDK 20 对虚拟线程进行了进一步优化。虚拟线程是轻量级的线程,能够大规模创建,并极大地简化了高并发编程的复杂度。
public class VirtualThreadExample {
public static void main(String[] args) throws InterruptedException {
Thread.startVirtualThread(() -> {
try {
Thread.sleep(1000);
System.out.println("Hello from a virtual thread!");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread.sleep(2000); // 等待虚拟线程完成
}
}
2. 记录模式(Record Patterns)(预览)
记录模式允许开发者在模式匹配中使用记录(Record),从而简化了对复杂数据结构的解构和匹配。JDK 20 引入了记录模式的第二次预览,增加了更多功能和更好的语法支持。
public record Point(int x, int y) {}
public class RecordPatternExample {
public static void main(String[] args) {
Object obj = new Point(10, 20);
if (obj instanceof Point(int x, int y)) {
System.out.println("Point x: " + x + ", y: " + y);
}
}
}
3. switch 增强(第四次孵化)
JDK 20 对模式匹配 switch
语句进行了进一步改进,支持更多类型和模式的匹配,并进一步优化了匹配逻辑。
public class PatternMatchingSwitchExample {
public static void main(String[] args) {
Object obj = "Hello";
String result = switch (obj) {
case String s when s.length() > 5 -> "Long String";
case String s -> "Short String";
case Integer i -> "Integer: " + i;
default -> "Unknown type";
};
System.out.println(result); // 输出: Long String
}
}
4. 外部函数和内存 API(第四次孵化)
外部函数和内存 API 提供了一种高效、安全的方式来操作非堆内存和调用本地代码。JDK 20 进一步增强了这些 API,增加了更多内存操作和函数调用支持。
import jdk.incubator.foreign.*;
public class ForeignMemoryExample {
public static void main(String[] args) {
try (MemorySegment segment = MemorySegment.allocateNative(1024)) {
MemoryAccess.setByteAtOffset(segment, 0, (byte) 42);
byte value = MemoryAccess.getByteAtOffset(segment, 0);
System.out.println("Value: " + value); // 输出: Value: 42
}
}
}
5. 结构化并发(第二次孵化)
结构化并发在 JDK 20 中进行了进一步的增强。
结构化并发,是一种多线程编程方法,目的是为了通过结构化并发 API 来简化多线程编程,并不是为了取代java.util.concurrent,目前处于孵化器阶段。
结构化并发将不同线程中运行的多个任务视为单个工作单元,从而简化错误处理、提高可靠性并增强可观察性。也就是说,结构化并发保留了单线程代码的可读性、可维护性和可观察性。结构化并发的基本 API 是 StructuredTaskScope。
StructuredTaskScope 支持将任务拆分为多个并发子任务,在它们自己的线程中执行,并且子任务必须在主任务继续之前完成。StructuredTaskScope 的基本用法如下:
try (var scope = new StructuredTaskScope<Object>()) {
Future<Integer> future1 = scope.fork(task1);
Future<String> future2 = scope.fork(task2);
// 等待线程完成
scope.join();
}
6. 向量 API(第五次孵化)
Vector API 允许开发者利用 SIMD 指令编写高性能的向量化代码。JDK 20 对 Vector API 进行了进一步优化,支持更多数据类型和向量操作。
import jdk.incubator.vector.*;
public class VectorExample {
public static void main(String[] args) {
var species = FloatVector.SPECIES_256;
var a = FloatVector.fromArray(species, new float[] {1, 2, 3, 4, 5, 6, 7, 8}, 0);
var b = FloatVector.fromArray(species, new float[] {8, 7, 6, 5, 4, 3, 2, 1}, 0);
var c = a.add(b);
float[] result = new float[species.length()];
c.intoArray(result, 0);
System.out.println(Arrays.toString(result)); // 输出: [9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0]
}
}