Java 18-20 过渡版本
2026/1/15大约 4 分钟JavaJava版本特性JavaJava新特性LambdaStreamOptional模块化虚拟线程
Java 18 (2022年3月)
默认 UTF-8 编码
// Java 18 之前,默认编码取决于操作系统
// Java 18 之后,默认编码为 UTF-8
// 不再需要显式指定
Files.readString(path); // 默认 UTF-8
Files.writeString(path, content); // 默认 UTF-8
// 查看默认编码
System.out.println(Charset.defaultCharset()); // UTF-8简单 Web 服务器
# 启动简单 HTTP 服务器
jwebserver
# 指定端口和目录
jwebserver -p 8080 -d /path/to/directory
# 绑定地址
jwebserver -b 0.0.0.0 -p 8080// 编程方式
var server = SimpleFileServer.createFileServer(
new InetSocketAddress(8080),
Path.of("/path/to/directory"),
SimpleFileServer.OutputLevel.VERBOSE
);
server.start();代码片段 API (JavaDoc)
/**
* 示例方法
*
* {@snippet :
* // 使用示例
* var list = List.of("a", "b", "c");
* list.forEach(System.out::println);
* }
*
* {@snippet file="Example.java" region="demo"}
*/
public void example() { }向量 API (第三次孵化)
// 性能优化的向量操作
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;
float[] vectorMultiply(float[] a, float[] b) {
float[] c = new float[a.length];
int i = 0;
int upperBound = SPECIES.loopBound(a.length);
for (; i < upperBound; i += SPECIES.length()) {
var va = FloatVector.fromArray(SPECIES, a, i);
var vb = FloatVector.fromArray(SPECIES, b, i);
va.mul(vb).intoArray(c, i);
}
for (; i < a.length; i++) {
c[i] = a[i] * b[i];
}
return c;
}外部函数和内存 API (第二次孵化)
// 调用本地函数
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle strlen = linker.downcallHandle(
stdlib.find("strlen").get(),
FunctionDescriptor.of(JAVA_LONG, ADDRESS)
);
try (Arena arena = Arena.openConfined()) {
MemorySegment str = arena.allocateUtf8String("Hello");
long len = (long) strlen.invoke(str);
}Java 19 (2022年9月)
虚拟线程 (预览)
轻量级线程,大幅提升并发性能。
// 创建虚拟线程
Thread vThread = Thread.ofVirtual().start(() -> {
System.out.println("Running in virtual thread");
});
// 使用工厂
ThreadFactory factory = Thread.ofVirtual().factory();
Thread t = factory.newThread(() -> System.out.println("Hello"));
// 虚拟线程执行器
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
// 结构化并发(孵化)
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<String> user = scope.fork(() -> fetchUser());
Future<Integer> order = scope.fork(() -> fetchOrder());
scope.join();
scope.throwIfFailed();
return new Response(user.resultNow(), order.resultNow());
}Record 模式 (预览)
record Point(int x, int y) {}
record Rectangle(Point topLeft, Point bottomRight) {}
// 解构 Record
static void printPoint(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println("x = " + x + ", y = " + y);
}
}
// 嵌套解构
static void printRectangle(Object obj) {
if (obj instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) {
System.out.println("From (" + x1 + "," + y1 + ") to (" + x2 + "," + y2 + ")");
}
}
// 在 switch 中使用
static String describe(Object obj) {
return switch (obj) {
case Point(int x, int y) -> "Point at " + x + ", " + y;
case Rectangle(Point p1, Point p2) -> "Rectangle from " + p1 + " to " + p2;
default -> "Unknown";
};
}Switch 模式匹配 (第三次预览)
// 守卫条件使用 when
static String classify(Object obj) {
return switch (obj) {
case String s when s.length() > 10 -> "long string";
case String s -> "short string";
case Integer i when i > 0 -> "positive";
case Integer i -> "non-positive";
case null -> "null";
default -> "other";
};
}外部函数和内存 API (预览)
// 从预览升级
try (Arena arena = Arena.openConfined()) {
MemorySegment segment = arena.allocate(100);
segment.set(ValueLayout.JAVA_INT, 0, 42);
int value = segment.get(ValueLayout.JAVA_INT, 0);
}Java 20 (2023年3月)
作用域值 (孵化)
替代 ThreadLocal 的更安全方案。
// 定义作用域值
static final ScopedValue<String> USER = ScopedValue.newInstance();
// 绑定值
ScopedValue.where(USER, "Alice").run(() -> {
System.out.println("User: " + USER.get());
processRequest();
});
// 嵌套绑定
ScopedValue.where(USER, "Alice").run(() -> {
System.out.println(USER.get()); // Alice
ScopedValue.where(USER, "Bob").run(() -> {
System.out.println(USER.get()); // Bob
});
System.out.println(USER.get()); // Alice
});虚拟线程 (第二次预览)
// 改进的 API
Thread.ofVirtual()
.name("worker-", 0)
.start(() -> {
System.out.println(Thread.currentThread().getName());
});
// 与结构化并发结合
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<String>()) {
scope.fork(() -> fetchFromSource1());
scope.fork(() -> fetchFromSource2());
scope.join();
return scope.result(); // 返回第一个成功的结果
}Record 模式 (第二次预览)
// 增强的类型推断
record Box<T>(T value) {}
static void process(Box<String> box) {
if (box instanceof Box(var s)) { // s 推断为 String
System.out.println(s.toUpperCase());
}
}
// 泛型 Record 模式
static <T> void printBox(Box<T> box) {
if (box instanceof Box(var value)) {
System.out.println(value);
}
}Switch 模式匹配 (第四次预览)
// 穷尽性检查改进
sealed interface Shape permits Circle, Rectangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double w, double h) implements Shape {}
static double area(Shape shape) {
return switch (shape) {
case Circle(var r) -> Math.PI * r * r;
case Rectangle(var w, var h) -> w * h;
// 不需要 default,编译器知道已穷尽
};
}外部函数和内存 API (第二次预览)
// 更简洁的 API
try (Arena arena = Arena.ofConfined()) {
// 分配内存
MemorySegment segment = arena.allocate(ValueLayout.JAVA_INT, 10);
// 调用本地函数
Linker linker = Linker.nativeLinker();
MethodHandle strlen = linker.downcallHandle(
linker.defaultLookup().find("strlen").get(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
);
}总结
| 版本 | 主要特性 |
|---|---|
| Java 18 | 默认 UTF-8、简单 Web 服务器、代码片段 API |
| Java 19 | 虚拟线程(预览)、Record 模式(预览)、结构化并发(孵化) |
| Java 20 | 作用域值(孵化)、虚拟线程(第二次预览)、Record 模式(第二次预览) |
Java 18-20 是 Java 17 到 Java 21 之间的过渡版本,主要用于预览和完善虚拟线程、Record 模式等重要特性。
