Java 21 新特性详解
Java 21 于 2023 年 9 月正式发布,是继 Java 17 之后的下一个长期支持版本(LTS)。本文将带你全面了解 Java 21 带来的重要新特性及其实际应用。
一、虚拟线程(Virtual Threads)—— JEP 444
虚拟线程是 Java 21 中最重磅的特性,它彻底改变了 Java 的并发编程模型。
什么是虚拟线程?
传统 Java 线程(平台线程)与操作系统线程是 1:1 映射的,创建和切换成本高。虚拟线程由 JVM 管理,是轻量级线程,可以创建数百万个而不会耗尽系统资源。
代码对比
传统方式:
ExecutorService executor = Executors.newFixedThreadPool(200);
for (int i = 0; i < 10000; i++) {
executor.submit(() -> {
// 受限于线程池大小,大量任务需要排队
var result = blockingHttpCall();
return process(result);
});
}
虚拟线程方式:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 100_000; i++) {
executor.submit(() -> {
// 每个任务一个虚拟线程,轻松支持十万级并发
var result = blockingHttpCall();
return process(result);
});
}
}
核心优势
- 轻量级:一个虚拟线程仅需几 KB 内存,可轻松创建百万级线程
- 兼容性:现有阻塞式代码无需修改即可使用
- 简化模型:告别复杂的响应式编程,回归简单的同步写法
- 高效调度:JVM 自动将虚拟线程调度到少量平台线程上执行
使用建议
// 方式一:直接创建
Thread.startVirtualThread(() -> System.out.println("Hello from virtual thread!"));
// 方式二:使用 Builder
Thread.ofVirtual().name("my-vt-", 0).start(() -> {
System.out.println(Thread.currentThread().getName());
});
// 方式三:使用 ExecutorService(推荐)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> doWork());
}
二、switch 模式匹配(Pattern Matching for switch)—— JEP 441
模式匹配让 switch 表达式更加灵活和安全,告别冗长的 instanceof 链。
基本用法
// 旧写法
static String format(Object obj) {
if (obj instanceof Integer i) {
return String.format("int %d", i);
} else if (obj instanceof Long l) {
return String.format("long %d", l);
} else if (obj instanceof Double d) {
return String.format("double %f", d);
} else if (obj instanceof String s) {
return String.format("String %s", s);
} else {
return obj.toString();
}
}
// Java 21 新写法
static String format(Object obj) {
return switch (obj) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
case null -> "null";
default -> obj.toString();
};
}
守卫模式(Guarded Patterns)
static void test(Object obj) {
switch (obj) {
case String s when s.length() > 10 -> System.out.println("长字符串: " + s);
case String s -> System.out.println("短字符串: " + s);
case Integer i when i > 0 -> System.out.println("正整数: " + i);
case Integer i -> System.out.println("非正整数: " + i);
default -> System.out.println("其他类型");
}
}
密封类(Sealed Classes)配合使用
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double a, double b, double c) implements Shape {}
static double area(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> {
double s = (t.a() + t.b() + t.c()) / 2;
yield Math.sqrt(s * (s - t.a()) * (s - t.b()) * (s - t.c()));
}
// 无需 default,编译器知道所有子类已被覆盖
};
}
三、Record 模式(Record Patterns)—— JEP 440
Record 模式允许直接解构 Record 对象,使数据处理更加简洁。
基本解构
record Point(int x, int y) {}
record Line(Point start, Point end) {}
// 旧写法
static void printX(Object obj) {
if (obj instanceof Point p) {
System.out.println(p.x());
}
}
// Java 21 新写法:直接解构
static void printX(Object obj) {
if (obj instanceof Point(var x, var y)) {
System.out.println("x = " + x + ", y = " + y);
}
}
// 嵌套解构
static void printLine(Object obj) {
if (obj instanceof Line(Point(var x1, var y1), Point(var x2, var y2))) {
System.out.printf("从 (%d,%d) 到 (%d,%d)%n", x1, y1, x2, y2);
}
}
在 switch 中使用
static String describe(Object obj) {
return switch (obj) {
case Point(0, 0) -> "原点";
case Point(var x, 0) -> "x 轴上的点: " + x;
case Point(0, var y) -> "y 轴上的点: " + y;
case Point(var x, var y) -> String.format("点 (%d, %d)", x, y);
case Line(Point(var x1, var y1), Point(var x2, var y2)) ->
String.format("线段 (%d,%d)->(%d,%d)", x1, y1, x2, y2);
default -> "未知形状";
};
}
四、序列化集合(Sequenced Collections)—— JEP 431
Java 21 引入了 SequencedCollection 接口,统一了有序集合的操作方式。
核心接口
// 新增的接口层次
SequencedCollection<E> // List, Deque 等
SequencedSet<E> // LinkedHashSet, TreeSet 等
SequencedMap<K, V> // LinkedHashMap, TreeMap 等
常用方法
SequencedCollection<String> list = new ArrayList<>(List.of("A", "B", "C"));
list.addFirst("X"); // [X, A, B, C]
list.addLast("Y"); // [X, A, B, C, Y]
list.getFirst(); // X
list.getLast(); // Y
list.reversed(); // [Y, C, B, A, X]
// Map 也支持了
SequencedMap<String, Integer> map = new LinkedHashMap<>();
map.putFirst("first", 1);
map.putLast("last", 2);
map.firstEntry(); // first=1
map.lastEntry(); // last=2
map.reversed(); // 反向视图
实际价值
// 以前获取最后一个元素很麻烦
List<String> list = getList();
String last = list.get(list.size() - 1); // 丑陋
// 现在一行搞定
String last = list.getLast();
五、未命名模式和变量(Unnamed Patterns & Variables)—— JEP 443
用下划线 _ 表示不需要使用的变量,提升代码可读性。
// 旧写法:不得不给变量命名
if (obj instanceof Point(var x, var y)) {
System.out.println(x); // y 未使用但必须声明
}
// 新写法:用 _ 忽略不需要的变量
if (obj instanceof Point(var x, _)) {
System.out.println(x); // 更清晰地表达意图
}
// switch 中使用
switch (obj) {
case Line(Point(var x, _), _) -> System.out.println("x 坐标: " + x);
default -> {}
}
// lambda 中使用
map.computeIfAbsent(key, _ -> new ArrayList<>());
// for 循环中使用
for (var _ : iterations) {
doSomethingRepeated();
}
六、分代 ZGC(Generational ZGC)—— JEP 439
ZGC 升级为分代收集,显著提升性能。
核心改进
- 分代管理:区分年轻对象和老年代对象
- 更高吞吐量:分代 ZGC 的吞吐量比非分代提升约 10-20%
- 更低延迟:最大暂停时间保持在亚毫秒级
- 更低内存占用:减少堆内存的使用量
启用方式
# Java 21 中 ZGC 默认就是分代的
java -XX:+UseZGC MyApplication
# 如果需要非分代模式(兼容性)
java -XX:+UseZGC -XX:-ZGenerational MyApplication
七、其他值得关注的特性
未命名类和实例主方法(JEP 447)—— 预览特性
降低 Java 入门门槛,适合初学者:
// 不需要 class 声明,不需要 public static void main
void main() {
System.out.println("Hello, Java 21!");
}
字符串模板(JEP 430)—— 预览特性
String name = "World";
int age = 25;
// 使用 STR 模板处理器
String msg = STR."Hello, \{name}! You are \{age} years old.";
// 结果: "Hello, World! You are 25 years old."
作用域值(Scoped Values)—— 预览特性
比 ThreadLocal 更安全、更高效的线程本地变量:
private static final ScopedValue<User> CURRENT_USER = ScopedValue.newInstance();
// 设置值
ScopedValue.runWhere(CURRENT_USER, user, () -> {
// 在此作用域内可以访问 CURRENT_USER.get()
handleRequest();
});
八、总结
| 特性 | 状态 | 影响程度 | 适用场景 |
|---|---|---|---|
| 虚拟线程 | 正式 | ⭐⭐⭐⭐⭐ | 高并发、I/O 密集型应用 |
| switch 模式匹配 | 正式 | ⭐⭐⭐⭐ | 复杂条件分支逻辑 |
| Record 模式 | 正式 | ⭐⭐⭐⭐ | 数据处理、解析 |
| 序列化集合 | 正式 | ⭐⭐⭐ | 日常集合操作 |
| 未命名变量 | 正式 | ⭐⭐⭐ | 代码可读性优化 |
| 分代 ZGC | 正式 | ⭐⭐⭐⭐ | 低延迟应用 |
Java 21 是一个里程碑式的 LTS 版本。 虚拟线程让 Java 在高并发场景下重获竞争力,模式匹配让代码更加简洁和类型安全,分代 ZGC 进一步巩固了 Java 在低延迟领域的地位。

浙公网安备 33010602011771号