Administrator
发布于 2022-08-27 / 2673 阅读
64

JDK 17 新特性全解析:为什么它是最好的 LTS

为什么我们卡在 JDK 8,却决定直接跳 17

团队基础组件升级评审会上,有人提议"升到 JDK 11 过渡一下"。我投了反对票:既然要动,不如直接到 JDK 17——它是继 8 之后第二个长期支持版本(LTS),2021 年 9 月发布,生态已经足够成熟,而 11 到 17 之间没有第二个 LTS,停在 11 等于再升一次。更重要的是,17 带了一票能直接改善代码质量的特性,我把最实用的几个写了出来。

record:把"纯数据载体"写得干净

以前一个 DTO 要写一堆字段、getter、equalshashCodetoString,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 升级真正的回报。

参考