从“远古 Java”到现代 JVM:Java 21 把 Java 6 按在地上摩擦的那些年

4 阅读6分钟

很多人公司里还跑着 Java 6、Java 7 的老项目。

你打开代码一看:

  • 满屏 new ArrayList<String>()
  • try-finally 手动关流
  • switch 只能写 case 1:
  • 日期处理靠 Date
  • 多线程靠手搓 Thread
  • JSON 解析全是工具类大战

而现在已经是 Java 21 的时代了。

Java 21 是 LTS(长期支持版),距离 Java 6 已经跨越了十几年的语言演进。很多当年“写 Java 很啰嗦”的痛点,今天其实都已经被官方解决了。

这篇文章不讲历史八卦,直接看:

Java 21 相比 Java 6,到底多了哪些真正影响开发体验的特性?

并且每个特性都配实际代码。


一、类型推断:终于不用写两遍类型了(var)

Java 6 写法

Map<String, List<User>> userMap = new HashMap<String, List<User>>();

老 Java 最大的问题:

你声明一次类型,还要再重复一次。

非常烦。


Java 21 写法

var userMap = new HashMap<String, List<User>>();

甚至:

var name = "Tom";
var age = 18;
var list = List.of("A", "B", "C");

代码一下清爽很多。


什么时候别用 var?

这个很多人容易走极端。

下面这种:

var x = doSomething();

如果方法名语义不明显,可读性会下降。

所以:

  • 类型明显 → 用 var
  • 类型不明显 → 老老实实写类型

这才是正确姿势。


二、集合工厂方法:告别一长串 add()

Java 6

List<String> list = new ArrayList<String>();
list.add("Java");
list.add("Python");
list.add("Go");

Java 21

var list = List.of("Java", "Python", "Go");

Map 也支持:

var map = Map.of(
        "name", "Tom",
        "age", "18"
);

这个改动看起来小。

但实际开发里:

代码量减少非常明显。

尤其是测试代码。


三、Lambda 表达式:Java 终于不像老干部了

Java 6

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("hello");
    }
}).start();

匿名内部类写到怀疑人生。


Java 21

new Thread(() -> System.out.println("hello")).start();

差距已经不是“一点点”。


四、Stream API:集合处理进入现代时代

Java 6 那会儿最经典的代码:

List<String> result = new ArrayList<String>();

for (String item : list) {
    if (item.startsWith("J")) {
        result.add(item.toUpperCase());
    }
}

Java 21:

var result = list.stream()
        .filter(item -> item.startsWith("J"))
        .map(String::toUpperCase)
        .toList();

Stream 最大的价值不是“炫技”。

而是:

  • 业务逻辑表达更清晰
  • 更适合并行处理
  • 更接近函数式思维

当然。

别为了 Stream 而 Stream。

有些复杂逻辑硬写链式调用,只会越来越难维护。


五、Text Block:终于不用疯狂拼字符串了

Java 6

String json = "{\n" +
        "  "name": "Tom",\n" +
        "  "age": 18\n" +
        "}";

看着都累。


Java 21

String json = """
        {
          "name": "Tom",
          "age": 18
        }
        """;

写 SQL 特别爽:

String sql = """
        SELECT id, name
        FROM user
        WHERE age > 18
        """;

这个特性一旦用了,就回不去了。


六、Switch 表达式:终于不像上世纪语法了

Java 6

String result;

switch (code) {
    case 1:
        result = "SUCCESS";
        break;
    case 2:
        result = "FAIL";
        break;
    default:
        result = "UNKNOWN";
}

Java 21

var result = switch (code) {
    case 1 -> "SUCCESS";
    case 2 -> "FAIL";
    default -> "UNKNOWN";
};

没有 break。

没有变量提前声明。

没有 case 穿透。

舒服很多。


七、Record:DTO 不再是样板代码地狱

以前 Java Bean:

public class User {

    private String name;
    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    @Override
    public String toString() {
        return ...
    }
}

真正业务代码没几行。

Getter/Setter 写了一堆。


Java 21:

public record User(String name, Integer age) {
}

自动生成:

  • 构造器
  • getter
  • equals
  • hashCode
  • toString

尤其适合:

  • DTO
  • 返回对象
  • 查询结果对象

八、Pattern Matching:instanceof 终于不反人类了

Java 6

if (obj instanceof String) {
    String str = (String) obj;
    System.out.println(str.length());
}

Java 21

if (obj instanceof String str) {
    System.out.println(str.length());
}

少一次强转。

但开发体验提升巨大。

这种优化特别“润物细无声”。


九、虚拟线程(Virtual Thread):Java 并发真正的大升级

这个是 Java 21 里最重量级的能力之一。

以前:

ExecutorService executor = Executors.newFixedThreadPool(200);

线程很贵。

不敢开太多。


Java 21:

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {

    for (int i = 0; i < 10000; i++) {
        executor.submit(() -> {
            Thread.sleep(1000);
            return null;
        });
    }
}

你甚至可以轻松开几十万级任务。


为什么重要?

传统线程:

  • 1 个线程 ≈ 1 个操作系统线程
  • 成本高
  • 内存占用大

虚拟线程:

  • JVM 管理
  • 极轻量
  • 特别适合 IO 密集型场景

比如:

  • Web 服务
  • RPC 调用
  • 数据库访问

很多以前必须上 Reactor、异步回调才能扛住的场景。

现在同步代码都能跑很高并发。

这对 Java 生态影响非常大。


十、新的日期时间 API:终于不用 Date 了

Java 6 的日期 API:

Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

问题:

  • API 设计混乱
  • 线程不安全
  • 时区容易炸

Java 21:

LocalDate today = LocalDate.now();

LocalDate nextWeek = today.plusWeeks(1);

System.out.println(nextWeek);

格式化:

var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

System.out.println(today.format(formatter));

这是 Java 生态里非常成功的一次 API 重构。


十一、Optional:少写很多 null 判断

Java 6

if (user != null && user.getAddress() != null) {
    System.out.println(user.getAddress().getCity());
}

Java 21

Optional.ofNullable(user)
        .map(User::getAddress)
        .map(Address::getCity)
        .ifPresent(System.out::println);

当然。

Optional 不是让你 everywhere 都用。

它更适合:

  • 返回值
  • 链式空值处理

而不是:

Optional<String> name;

这种字段级滥用。


十二、模块化(JPMS)

Java 9 引入。

以前:

  • Jar 地狱
  • 包冲突
  • 类路径混乱

现在:

module com.demo.app {
    requires java.sql;
}

大型项目治理会舒服很多。

不过现实里:

很多公司还没真正用起来。


十三、SequencedCollection:集合终于有“头尾”统一操作了

Java 21 新特性。

以前:

LinkedList<String> list = new LinkedList<>();
list.addFirst("A");
list.addLast("B");

不同集合 API 不统一。


Java 21:

SequencedCollection<String> list = new LinkedList<>();

list.addFirst("A");
list.addLast("B");

统一了:

  • first
  • last
  • reverse

集合 API 更规整。


十四、字符串增强

repeat()

"-".repeat(10);

isBlank()

str.isBlank();

lines()

text.lines().forEach(System.out::println);

这些看似“小功能”。

但天天写业务的人知道:

高频小优化,最提升幸福感。


十五、HTTP Client:终于不用 HttpURLConnection 了

Java 6:

HttpURLConnection conn = ...

又臭又长。


Java 21:

var client = HttpClient.newHttpClient();

var request = HttpRequest.newBuilder()
        .uri(URI.create("https://example.com"))
        .build();

var response = client.send(
        request,
        HttpResponse.BodyHandlers.ofString()
);

System.out.println(response.body());

现代很多项目已经不一定需要第三方 HTTP 库了。


十六、GC 进化:性能不是一个时代

Java 6 时代主流:

  • Serial GC
  • Parallel GC
  • CMS

而 Java 21:

  • G1
  • ZGC
  • Shenandoah

暂停时间和吞吐能力已经完全不是一个时代。

尤其:

ZGC

目标:

超低停顿。

哪怕几十 GB 堆内存,也能做到非常低的 STW。

对于大内存服务非常关键。


十七、Preview 特性:Java 开始敢“进化”了

以前 Java 更新特别保守。

现在:

  • Pattern Matching
  • String Template
  • Scoped Value
  • Structured Concurrency

很多能力会先 Preview。

社区反馈后再正式发布。

这意味着:

Java 已经不是那个“十年不变”的语言了。


最后:Java 21 最大的变化,其实不是语法

很多人会觉得:

“不就是语法糖吗?”

其实不是。

Java 21 最大的变化是:

Java 开始重视“开发者体验”了

过去:

  • 冗长
  • 啰嗦
  • 模板代码多

现在:

  • 更现代
  • 更简洁
  • 更适合云原生
  • 更适合高并发

尤其虚拟线程出来之后。

Java 在服务端领域的生命力,又被续了一大口。


如果现在还在 Java 6/7/8 怎么办?

建议路线:

  • Java 8 → 至少升 17
  • 新项目 → 直接 21

因为:

  • 17/21 是 LTS
  • 生态支持已经成熟
  • 性能提升巨大
  • 开发效率提升明显

很多老项目不升级,不是因为不能升。

而是:

“没人敢动。”

但越拖,技术债越重。

这几乎是所有 Java 老系统的共同命运。