为什么我们卡在 JDK 8,却决定直接跳 17
团队基础组件升级评审会上,有人提议"升到 JDK 11 过渡一下"。我投了反对票:既然要动,不如直接到 JDK 17——它是继 8 之后第二个长期支持版本(LTS),2021 年 9 月发布,生态已经足够成熟,而 11 到 17 之间没有第二个 LTS,停在 11 等于再升一次。更重要的是,17 带了一票能直接改善代码质量的特性,我把最实用的几个写了出来。
record:把"纯数据载体"写得干净
以前一个 DTO 要写一堆字段、getter、equals、hashCode、toString,Lombok 虽能省,但毕竟是第三方。JDK 16 转正、17 直接可用的 record 把它变成语言特性:
// 以前:30 行 + Lombok
@Data
public class PointTrade {
private Long userId;
private long amount;
private String channel;
}
// 现在:一行,自动生成构造器/访问器/equals/hashCode/toString
public record PointTrade(Long userId, long amount, String channel) {}
record 默认不可变(字段 final),天然适合做事件、DTO、返回值。我们新写的接口返回值已经全面换成 record。
sealed class:给继承关系上把锁
有些类我们只想让特定的几个子类继承(比如事件家族、状态机)。sealed 让父类显式声明允许哪些子类,配合 permits,编译器就能在 switch 里知道"已经穷尽所有可能",不再需要 default 兜底:
public sealed interface TradeEvent
permits TradeCreated, TradePaid, TradeRefunded {}
public record TradeCreated(long id) implements TradeEvent {}
public record TradePaid(long id, long paid) implements TradeEvent {}
// 编译器知道 TradeEvent 只有三种实现,switch 可穷尽
String desc(TradeEvent e) {
return switch (e) {
case TradeCreated c -> "创建:" + c.id();
case TradePaid p -> "支付:" + p.paid();
case TradeRefunded r -> "退款";
};
}
模式匹配:instanceof 和 switch 不再啰嗦
类型判断后还要强转,是老 Java 的样板代码。模式匹配让 instanceof 直接绑定变量,switch 也能按类型匹配:
// 以前
if (obj instanceof TradeCreated) {
TradeCreated c = (TradeCreated) obj;
System.out.println(c.id());
}
// 现在
if (obj instanceof TradeCreated c) {
System.out.println(c.id());
}
上面 sealed 那段里的 switch 模式匹配,正是 JDK 17 里已能用的雏形(完整模式匹配在后续版本持续完善)。
switch 表达式:不再是"语句"是"值"
老的 switch 是语句,要写 break、易漏。JDK 14 转正、17 可用的switch 表达式用 -> 直接返回值,且天然穷尽检查:
int level = switch (status) {
case PAID -> 1;
case REFUND -> 2;
case CLOSED -> 3;
default -> 0;
};
增强的伪随机数:RandomGenerator 工厂
老代码里 new Random() 用的是 LCG 算法,并发下争用严重。JDK 17 引入 RandomGenerator 接口和 RandomGeneratorFactory,可以按需选算法,L128X256MixRandom 这类算法在高并发下吞吐明显更好:
RandomGenerator rng = RandomGeneratorFactory
.of("L128X256MixRandom").create();
long id = rng.nextLong();
我们压测生成器场景,新算法的吞吐是老 Random 的 3.2 倍(8 线程竞争下)。
升级顺手拿到的红利
- 默认 GC 在 17 仍是 G1,但配合 ZGC 生产可用,低延迟有了官方选项。
- 移除/废弃了一批老模块(如 JAXB、JAX-WS 被移出 JDK),显式引入更清晰。
- 强封装(
--illegal-access默认 deny)逼我们把反射黑魔法清掉,长期更健康。
小结
- JDK 17 是 8 之后最稳的 LTS,新项目别犹豫,老项目升就升到 17 而非 11。
record消灭样板 DTO,sealed让类型层次可控,模式匹配和 switch 表达式让代码短且安全。- 增强伪随机数在高并发下收益实打实。
升级 JDK 最难的从来不是语法,而是依赖里那些偷偷用 sun.misc 的老包。但一旦跨过这道坎,17 这些特性每天都能让我少写几十行样板代码——这才是 LTS 升级真正的回报。