Java 新特性完全指南:从 JDK 8 到 JDK 26,这门语言悄悄变了个样

2 阅读13分钟

2026年3月17日,Oracle 发布了 JDK 26。从 JDK 8 到 JDK 26,Java 已经走过了近 18 年。

很多人对 Java 的印象还停留在"JDK 8 够用了"的阶段,殊不知这门"老语言"早已在悄悄自我革新。var 类型推断、文本块、Records、Sealed Classes、模式匹配、虚拟线程……每半年一次的版本更新,都让 Java 代码变得更简洁、更现代、更有表现力。

本文从 JDK 9 一路写到 JDK 26,每个版本挑最亮眼的 1-2 个特性,用「以前这么写 vs 现在这么写」的对比方式,让你直观感受这些变化的魅力。先郑重声明:JDK 版本众多,每个版本的 JEP 少则几个、多则十几个,本文只挑日常写代码最常用、对代码质量影响最大的特性来讲,完整的 JEP 列表会附在文末。


JDK 9:模块化系统来了,文本块初露锋芒

是什么

JDK 9 是继 JDK 8 之后最大的架构变革,引入了 JPMS(Java Platform Module System) ,把 Java 应用从"一堆 JAR 包"变成了"有边界、可复用的模块"。同时,文本块(Text Blocks)以预览特性登场。

模块系统:以前这么写

// 没模块之前,JAR 包之间依赖关系不清晰
// 全局可见,想用什么就拿什么,一不小心就耦合成屎山

现在这么写

// module-info.java
module com.example.myapp {
    requires com.example.utils;   // 明确依赖
    exports com.example.api;       // 明确导出哪些包
    opens com.example.internal;    // 明确哪些包可反射
}

模块化让大型项目有了更清晰的边界。Spring Boot 3 和 Jakarta EE 都在往模块化迁移,这是现代 Java 架构的必经之路。

文本块预览:以前这么写

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

现在这么写

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

文本块用三引号 """ 包裹多行字符串,从此告别 + "\n" + 的拼接噩梦。特别适合写 SQL、JSON、HTML 等多行字符串场景。


JDK 10:var 横空出世,样板代码砍一半

是什么

JDK 10 带来了 var 局部类型推断关键字,编译器会自动推断变量类型,开发者不需要重复写类型名。

以前这么写

String name = user.getName();
List<Map<String, Object>> data = queryData();
Optional<UserEntity> userOpt = userRepository.findById(id);

现在这么写

var name = user.getName();
var data = queryData();
var userOpt = userRepository.findById(id);

简洁度直接拉满,而且类型安全——var 不是弱类型,编译后还是强类型的。

注意

  • var 只能用局部变量,不能用字段、方法参数、返回值
  • var 必须有初始值,否则编译器推不出来
  • 链式调用特别长的时候慎用,不然回头看代码都不知道这个变量是什么类型

JDK 11:HTTP Client 终于原生支持,ZGC 上线

是什么

JDK 11 是一个 LTS 版本,带来了两个重磅特性:原生 HTTP Client API(支持 HTTP/2 和异步)和 ZGC(低延迟垃圾收集器)。

以前这么写(HTTP 请求)

// 用 HttpURLConnection,API 极其繁琐
URL url = new URL("https://api.example.com/data");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// 还要自己处理流、解析响应……写了20行才拿到一个JSON

现在这么写

// JDK 11 原生 HTTP Client
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/data"))
    .GET()
    .build();

HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.body());

支持同步和异步,支持 HTTP/2,性能比 HttpURLConnection 好出一大截。JDK 26 还给它加上了 HTTP/3 支持(见后文)。

ZGC:以前不敢想的低延迟

# 启动参数加一行,打开 ZGC
java -XX:+UseZGC -Xmx16g myapp.jar

ZGC 的停顿时间控制在毫秒级以内(通常 < 1ms),无论堆多大都不会有明显停顿。以前 GC 导致的业务卡顿,用 ZGC 几乎可以忽略不计。


JDK 12-13:Switch 表达式和文本块持续打磨

是什么

JDK 12-13 对两个预览特性进行了持续迭代:Switch 表达式文本块

Switch 表达式预览:以前这么写(JDK 8)

int result;
switch (day) {
    case MONDAY:
    case FRIDAY:
        result = 6;
        break;
    case TUESDAY:
        result = 7;
        break;
    // ...漏写一个 break 就是bug
    default:
        result = 0;
}

现在这么写(JDK 14+ 箭头语法)

int result = switch (day) {
    case MONDAY, FRIDAY -> 6;
    case TUESDAY        -> 7;
    case THURSDAY       -> 8;
    default             -> 0;
};

箭头语法返回值,不需要 break,也不会漏掉 case,简洁又安全。

文本块从预览到接近正式

JDK 13 文本块增加了两个转义序列:\s(保留末尾空格)和 ""(在文本块内表示双引号),让它更接近生产可用。


JDK 14-15:Records 和 Sealed Classes 登场,POJO 大解放

是什么

JDK 14-15 是两个版本的预览期,Records(不可变数据类)和 Sealed Classes(密封类)先后进入预览,日渐成熟。

Records:以前这么写

写一个只存数据的类,要手写构造器、Getter、equals、hashCode、toString:

public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() { return x; }
    public int getY() { return y; }

    @Override
    public boolean equals(Object o) { /* 15行 */ }
    @Override
    public int hashCode() { /* 5行 */ }
    @Override
    public String toString() { return "Point{x=" + x + ", y=" + y + '}'; }
}

现在这么写

public record Point(int x, int y) {}

就一行,自动获得:私有 final 字段、全参构造器、Getter(注意是 x() 不是 getX())、equals、hashCode、toString。

Sealed Classes 预览:精确控制谁可以继承

// Shape 只有 Circle 和 Square 能继承
public sealed class Shape permits Circle, Square {}
public final class Circle extends Shape {}
public non-sealed class Square extends Shape {}

适合 DDD 值对象、策略模式、规则引擎等场景——你想让谁继承,你说了算。


JDK 16:Records 和 instanceof 模式匹配正式转正

是什么

Records 和 instanceof 模式匹配(JDK 14 预览)正式成为标准特性,可以放心在生产环境使用。

instanceof 模式匹配:以前这么写

if (obj instanceof String) {
    String s = (String) obj;  // 重复写类型,还要手动强转
    if (s.length() > 5) {
        System.out.println(s.toUpperCase());
    }
}

现在这么写(JDK 16+)

if (obj instanceof String s && s.length() > 5) {
    System.out.println(s.toUpperCase());  // s 直接用,不需要强转
}

instanceof 后面直接声明变量 s,类型自动推断,不需要再写 (String) obj 强转。


JDK 17:Sealed Classes 正式转正,Switch 表达式也稳了

是什么

JDK 17 是继 JDK 11 之后的又一个 LTS 版本。Sealed Classes 和 Switch 表达式在这一版本正式 GA,生产使用无顾虑。

同时 JDK 17 开始,免费提供 JDK 版本从"仅供开发"升级为生产使用也免费(Oracle JDK),这对企业用户是个重大利好。


JDK 18-20:默默积累,String Templates 初现

是什么

这几个版本的核心变化主要在库层面,亮点不多但积累很深:

  • JDK 18:默认启用 UTF-8 编码(再也不用担心中文乱码了),引入了 java.net.spi.InetAddress 的改进
  • JDK 19虚拟线程(Project Loom)第一次预览登场!
  • JDK 20:虚拟线程第二次预览,模式匹配持续完善

虚拟线程在 JDK 19 第一次预览出来后,社区反响强烈。这个特性从根本上解决了 Java 并发编程中"线程是稀缺资源"的痛点。


JDK 21:史上最强 LTS,虚拟线程正式转正 ⭐⭐⭐

是什么

JDK 21 是 Java 历史上里程碑式的 LTS 版本,虚拟线程正式转正、Switch 模式匹配完整落地、Sequenced Collections 补全集合框架最后一块短板。

虚拟线程:以前这么写

// 1000个并发任务 = 1000个线程 = 内存爆炸
ExecutorService executor = Executors.newFixedThreadPool(1000);
for (int i = 0; i < 1000; i++) {
    final int taskId = i;
    executor.submit(() -> {
        doIOOperation(taskId);  // 大多数时间在等 IO
        return null;
    });
}

现在这么写(JDK 21+)

// 100万个虚拟线程同时运行,轻轻松松
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 1_000_000).forEach(i ->
        executor.submit(() -> doIOOperation(i))
    );
}

每个任务一个协程,可以 hold 住百万级并发 IO!内存占用从 GB 级降到 MB 级。

注意:虚拟线程只适合 IO 密集型任务。CPU 密集型任务还是老老实实用线程池。

Sequenced Collections:终于有"有序集合"标准接口了

// JDK 21 之前,没有统一的方式获取第一个/最后一个元素
// JDK 21 引入 SequencedCollection 接口
SequencedCollection<String> list = new ArrayList<>();
list.addFirst("first");
list.addLast("last");
System.out.println(list.getFirst());  // first
System.out.println(list.getLast());  // last

Switch 模式匹配完整版(JEP 441)

// 以前 switch 只能匹配常量,现在可以匹配类型和结构
String formatted = switch (obj) {
    case Integer i -> String.format("int: %d", i);
    case String s  -> String.format("str: %s", s.toUpperCase());
    case null, default -> "unknown";
};

JDK 22-23:外部函数 API 转正,未命变量登场

是什么

JDK 22-23 带来了大量 Preview 特性成熟落地,以及一些语言级别的细微改进。

未命变量和模式(JEP 456 正式特性)

// 不需要用到的变量,用 _ 占位
for (int i = 0, _ = initialize(i); i < 10; i++) {
    System.out.println(i);
}

// switch 中也不需要每个 case 都用变量
switch (shape) {
    case Circle _   -> drawCircle();
    case Rectangle _ -> drawRectangle();
}

外部函数和内存 API(JEP 454 正式特性)

这是 Java 历史上里程碑式的特性——Java 程序可以直接调用 C 函数和操作原生内存,不再需要 JNI:

// JDK 22 外部函数 API(无需 JNI)
MemorySegment segment = MemorySegment.allocateNative(100);

这为高性能计算、AI 推理等领域打开了大门,未来 Java 可以直接对接 native 生态。

文本块终于正式(JDK 22)

字符串模板在 JDK 21 预览后,JDK 22 继续打磨(最终在 JDK 25 正式转正)。

Markdown 文档注释(JEP 467 正式特性)

/**
 * # 计算两个数的和
 *
 * 这是一个 **加法** 方法。
 *
 * @param a 第一个数
 * @param b 第二个数
 */
public static int add(int a, int b) { return a + b; }

JavaDoc 里终于可以写 Markdown 了,文档可读性大幅提升。


JDK 24:紧凑对象头上线,内存省一大截

是什么

JDK 24 带来了紧凑对象头(JEP 519 正式化),将对象头从 96-128 位缩减至 64 位,堆内存占用显著下降。

# 启动时加上这个参数
java -XX:+UseCompactObjectHeaders -Xmx16g myapp.jar

对于高并发场景下大量小对象的 Java 应用(比如 RPC 框架、缓存系统),这个优化能让内存使用量直接降 20-30%,部署密度大大提升。

Stream API 增强

Stream.toList() 从 JDK 16 的预览变成了默认行为,Stream.gather() 在 JDK 23 第二次预览后继续完善,链式数据处理更优雅。


JDK 25:最新 LTS,String Templates 正式登场 ⭐⭐

是什么

JDK 25 于 2025 年 9 月发布,是目前最新的 LTS 版本(Oracle JDK 25 提供至 2031年的长期支持)。

String Templates 正式化(JEP 468)

这是继文本块之后,多行字符串处理的又一次飞跃:

// JDK 25 String Templates 正式版
String name = "张三";
int score = 95;
// STR 处理器支持嵌入表达式
String message = STR."Hello, {name}! Your score is {score}.";

// 多行模板
String html = STR."""
    <div>
        <h1>{title}</h1>
        <p>{content}</p>
    </div>
    """;

模板表达式 {...} 可以嵌入任何 Java 表达式,运行时直接求值。比字符串拼接更安全(减少 SQL 注入风险),比 String.format 更直观。

Scoped Values(JEP 506 正式特性)

比 ThreadLocal 更好用的线程内共享机制,天然支持虚拟线程:

static final ScopedValue<String> USER = new ScopedValue<>();

// 设置值
ScopedValue.where(USER, "张三")
    .run(() -> {
        // 虚拟线程间共享,安全且高效
        System.out.println(USER.get());  // 张三
    });

紧凑源文件与实例 main 方法(JEP 512)

// 一个文件搞定 Hello World,不需要类名
void main() {
    System.out.println("Hello, Java 25!");
}

JDK 26:HTTP/3 来了,G1 吞吐量暴涨

是什么

JDK 26 于 2026年3月17日 正式发布,是 JDK 25 之后的第一个非 LTS 版本,带来了 10 个 JEP,涵盖网络、性能、安全等多个维度。

HTTP/3 支持正式化(JEP 517)⭐

// 自动协商协议(推荐方式)
HttpClient client = HttpClient.newHttpClient();

// 明确指定 HTTP/3
HttpClient client = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_3)
    .build();

基于 QUIC 协议(UDP),0-RTT 握手消除队头阻塞连接迁移(Wi-Fi 切移动数据不丢连接),高丢包网络下性能大幅提升。不用改一行业务代码,只需要升级 JDK,就能享受 HTTP/3 的速度提升。

G1 GC 吞吐量暴涨(JEP 522)⭐

JDK 26 对 G1 GC 的写屏障做了大手术,通过双卡表机制,将 x64 架构下的写屏障指令从约 50 条压缩到约 12 条:

场景吞吐量提升
频繁修改引用字段+5%~15%
不频繁修改引用+5%

这对微服务、数据库连接池等引用操作密集型应用是重大利好。

AOT 对象缓存支持所有 GC(JEP 516)

这是 Project Leyden 的又一次里程碑。AOT 缓存现在可以用在任何 GC 上,包括 ZGC:

对比JDK 24(AOT 缓存)JDK 26(AOT 缓存)
支持 GC仅 G1所有 GC(含 ZGC)
训练阶段和生产阶段必须同一种 GCGC 可不同

这对 Serverless 和云原生应用意义重大——训练时用 G1,生产时用 ZGC,冷启动时间大幅缩短。

final 字段真正不可变(JEP 500)

JDK 26 开始,通过反射修改 final 字段会触发 JVM 警告:

// JDK 26+ 会发出警告
Field field = MyClass.class.getDeclaredField("NAME");
field.setAccessible(true);
field.set(null, "新值");  // ⚠️ Warning: final field mutation detected

为未来版本默认禁止此类操作做准备,Java 的完整性安全更进一步。

移除 Applet API(JEP 504)

Applet 这个上世纪的浏览器插件技术终于被彻底扫进历史垃圾堆,JDK 体积又小了一点。


一张图总结:JDK 9-26 特性选版指南

版本类型核心特性减少样板代码量
JDK 9特性模块系统、文本块预览★★★★★ 多行字符串
JDK 10特性var 类型推断★★★★☆ 局部变量
JDK 11LTSHTTP Client API、ZGC★★★★★ HTTP/并发
JDK 12-13预览迭代Switch 表达式、文本块★★★★☆ 分支逻辑
JDK 14-15预览迭代Records、Sealed Classes★★★★★ POJO/继承控制
JDK 16特性Records 正式、instanceof 模式匹配★★★★☆ 类型判断
JDK 17LTSSealed Classes 正式、Switch 正式★★★☆☆ 类族控制
JDK 18-20积累虚拟线程预览(Loom)、UTF-8 默认★★★★☆ 并发
JDK 21LTS ⭐虚拟线程正式、Sequenced Collections★★★★★ 并发/集合
JDK 22特性外部函数 API、未命变量★★★★☆ 原生互操作
JDK 23特性Markdown 文档、Stream Gatherers 预览★★★☆☆ 文档/流处理
JDK 24特性紧凑对象头、Stream API 增强★★★☆☆ 内存优化
JDK 25LTS ⭐String Templates 正式、Scoped Values★★★★★ 字符串/并发
JDK 26特性HTTP/3、G1 吞吐量优化★★★★☆ 网络/GC

总结:Java 正在变成你想不到的样子

写完这篇文章,我自己最大的感受是:Java 变年轻了。

从 JDK 8 到 JDK 26,这门语言没有吃老本,而是一直在进化:

  • var 让你少写重复的类型名
  • Records 让你告别 Lombok 的黑魔法
  • Sealed Classes 让你精确控制继承关系
  • 虚拟线程 让你用同步写法写高性能并发程序
  • String Templates 让你更安全地拼接字符串
  • HTTP/3 让你不动代码就能提升网络性能

如果你的团队还在用 JDK 8,不妨先从 var 和 Records 入手,感受一下现代 Java 的简洁。等 JDK 21 或 JDK 25 的 LTS 稳定了,虚拟线程 + String Templates 绝对值得迁移。

你们公司现在用的是什么 JDK 版本?有没有哪个新特性用了就回不去的?评论区聊聊 👇