一、核心与革命性特性

1. 虚拟线程 - JEP 444

这是 Java 21 最重磅的特性,旨在彻底简化并发编程。

  • 是什么? 轻量级线程,由 JVM 管理,而非操作系统。创建和切换成本极低,可以轻松创建数百万个虚拟线程。
  • 解决了什么问题? 传统平台线程(OS线程)重量级,数量有限。在处理大量并发I/O任务(如万级网络请求)时,线程池容易成为瓶颈,导致资源浪费(线程大部分时间在等待)。
  • 如何工作? 开发者仍然使用熟悉的 Thread API 和 ExecutorService。你可以像这样启动一个虚拟线程:

    java复制代码

    // 方式一:直接启动
    Thread.startVirtualThread(() -> {
        System.out.println("Hello, Virtual Thread!");
    });
    
    // 方式二:使用构建器
    Thread.ofVirtual().name("my-vt").start(() -> {...});
    
    // 方式三:使用 ExecutorService
    try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
        IntStream.range(0, 10_000).forEach(i -> {
            executor.submit(() -> {
                Thread.sleep(Duration.ofSeconds(1));
                return i;
            });
        });
    } // 自动等待所有任务完成
    
  • 核心优势: 用同步的代码风格获得异步的性能。你不再需要复杂的回调或反应式编程模型来处理高并发I/O,代码可读性和可维护性大大提升。
2. 序列集合 - JEP 431

为有序集合引入了新的接口,定义了明确的访问第一个和最后一个元素的方法。

  • 新接口: SequencedCollectionSequencedSetSequencedMap
  • 提供了什么?
    • addFirst(E)addLast(E)
    • getFirst()getLast()
    • removeFirst()removeLast()
    • reversed(): 返回一个逆序视图
  • 示例:

    java复制代码

    SequencedCollection<String> list = new ArrayList<>();
    list.add("A"); // [A]
    list.addFirst("B"); // [B, A]
    list.addLast("C"); // [B, A, C]
    
    System.out.println(list.getFirst()); // B
    System.out.println(list.getLast()); // C
    
    SequencedCollection<String> reversed = list.reversed();
    System.out.println(reversed); // [C, A, B]
    
  • 受益集合: ArrayListLinkedListLinkedHashSetTreeSet, 以及 LinkedHashMap 等现在都实现了这些接口。

二、语言特性增强(模式匹配的最终拼图)

这些特性使代码更简洁、更安全、更具表现力。

3. 记录模式 - JEP 440

允许在模式匹配中解构记录对象,是模式匹配功能的重要扩展。

  • 示例(Before Java 21):

    java复制代码

    record Point(int x, int y) {}
    
    // 老方法:需要显式检查类型并手动解构
    if (obj instanceof Point) {
        Point p = (Point) obj;
        System.out.println(p.x() + ", " + p.y());
    }
    
  • 示例(With Java 21):

    java复制代码

    // 新方法:直接解构
    if (obj instanceof Point(int x, int y)) {
        System.out.println(x + ", " + y); // 直接使用x和y
    }
    
  • 可以嵌套: 可以解构记录中的记录。

    java复制代码

    record Rectangle(Point topLeft, Point bottomRight) {}
    
    if (rect instanceof Rectangle(Point(var x1, var y1), Point(var x2, var y2))) {
        // 直接使用 x1, y1, x2, y2
    }
    
4. Switch 的模式匹配 - JEP 441

正式版。允许在 case 标签中直接使用类型模式,大大简化了基于类型的多路分发。

  • 示例(Before Java 21):

    java复制代码

    static String formatter(Object obj) {
        String formatted = "unknown";
        if (obj instanceof Integer i) {
            formatted = String.format("int %d", i);
        } else if (obj instanceof Long l) {
            formatted = String.format("long %d", l);
        } else if (obj instanceof String s) {
            formatted = String.format("String %s", s);
        }
        return formatted;
    }
    
  • 示例(With Java 21):

    java复制代码

    static String formatterPatternSwitch(Object obj) {
        return switch (obj) {
            case Integer i -> String.format("int %d", i);
            case Long l    -> String.format("long %d", l);
            case String s  -> String.format("String %s", s);
            case null      -> "Oops, it's null"; // 可以直接处理null
            default        -> obj.toString();
        };
    }
    
  • 优势: 代码更清晰,更安全(穷尽性检查),可直接处理 null
5. 未命名模式和变量 - JEP 443

允许使用下划线 _ 代替未使用的模式或变量名,减少混乱。

  • 示例:

    java复制代码

    // 场景一:在catch块中,异常对象e用不到
    try { ... }
    catch (Exception _) { // 用 _ 代替 e,表明我们不关心异常对象本身
        System.out.println("Something went wrong");
    }
    
    // 场景二:在记录模式中,不关心某个组件
    if (obj instanceof Point(int x, _)) { // 只关心x,不关心y
        System.out.println("X is: " + x);
    }
    
    // 场景三:增强型for循环中,索引用不到
    for (int i = 0, _ = sideEffect(); i < 10; i++) { ... }
    
6. 未命名类和实例 main 方法 - JEP 445 (预览)

旨在简化 Java 的学习门槛,允许更灵活的类声明和 main 方法定义。

  • 简化版 main 方法(无需 public static):

    java复制代码

    // 可以直接这样写,对于初学者更友好
    void main() {
        System.out.println("Hello, Simplified World!");
    }
    
  • 未命名类: 甚至可以省略类声明,直接将代码放在文件中(此特性主要用于教学和小型脚本)。

三、API 与性能改进

7. 分代 ZGC - JEP 439

通过为 ZGC 垃圾收集器引入分代机制,显著降低了垃圾收集的开销,提高了应用程序的性能。

  • 原理: 将堆内存分为年轻代和老年代。大多数对象都是“朝生夕死”的,分代后,ZGC 可以更频繁、更快速地收集年轻代,从而减少停顿时间和整体开销。
  • 目标: 在几乎不需要调优的情况下,为需要低延迟和高吞吐量的应用提供卓越性能。
8. 字符串模板 - JEP 430 (预览)

提供一种更安全、更便捷的字符串插值方式,比字符串拼接更 readable,比 String.format 更安全。

  • 示例:

    java复制代码

    String name = "Alice";
    int age = 30;
    
    // 传统方式
    String message1 = "Hello, " + name + ", you are " + age + " years old.";
    String message2 = String.format("Hello, %s, you are %d years old.", name, age);
    
    // 字符串模板(预览)
    String message = STR."Hello, \{name}, you are \{age} years old.";
    
  • 优势: 模板在编译时会进行验证,避免运行时错误(如类型不匹配)。它还支持自定义模板处理器,实现高级功能(如SQL模板防注入、JSON模板等)。
9. 外部函数与内存 API - JEP 442 (第三次预览后定稿)

替代不安全的 JNI,提供一种纯 Java 的方式来与本地代码(如 C/C++ 库)和堆外内存进行安全、高效的交互。此 API 在 Java 21 中正式定稿。

总结

Java 21 的特性矩阵可以总结如下:

特性 类型 状态 重要性
虚拟线程 并发 正式版 ⭐⭐⭐⭐⭐(革命性)
序列集合 API 正式版 ⭐⭐⭐(实用增强)
记录模式 语言 正式版 ⭐⭐⭐⭐(重要拼图)
Switch 模式匹配 语言 正式版 ⭐⭐⭐⭐(重要拼图)
未命名模式和变量 语言 正式版 ⭐⭐(锦上添花)
分代 ZGC 性能 正式版 ⭐⭐⭐⭐(重要性能提升)
字符串模板 语言 预览 ⭐⭐⭐(未来可期)
未命名类和 main 方法 语言 预览 ⭐(简化入门)
外部函数与内存 API API 正式版 ⭐⭐⭐(系统级开发生态)

核心建议:

  • 虚拟线程 是所有Java开发者都必须了解和学习的特性,它将改变我们编写高并发应用的方式。
  • 模式匹配 的一系列特性(记录模式、switch模式匹配)让Java的代码风格更加现代化和安全。
  • 对于新项目,尤其是微服务和云原生应用,Java 21 的虚拟线程和性能改进提供了强大的竞争力。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐