Java sealed classes 的隐藏陷阱

Java sealed classes and exhaustive pattern matching

Java 17 引入的 sealed classes 让模式匹配变得像 Haskell 一样优雅,编译器能自动检查是否覆盖了所有情况,无需 default 分支。但这背后有个致命陷阱:一旦你在公共 API 中暴露了 sealed 类型,新增子类型时,未重新编译的旧代码不会报错,而是等到运行时抛出 MatchException。这意味着所谓的“编译期安全”在跨模块场景下可能失效。作者认为,sealed classes 更适合组件内部使用,若强行用于公开 API,反而可能埋下运行时崩溃的隐患。

对于我而言,结论是 sealed 类型在组件内部实现中可能最有用,而当组件通过公共 API 向其他组件暴露时,其用处则较小。
  1. shepherdjerred

    真没想到 Java 已经进步到这种程度了。不过我还是更喜欢 TypeScript,因为我做很多前端工作,倾向于在全栈中使用同一种语言。

    话说回来,TypeScript 也能做穷尽模式匹配!https://github.com/gvergnaud/ts-pattern

  2. armchairhacker

    Java 也有递归模式,还有(可能仍处于预览阶段)字面量模式:`switch (x) { case A(B(true, var c)) -> f(c); }`

  3. another_twist

    我花了一段时间才习惯 sealed,当时也没太看出它的用处。但 AI 似乎很喜欢 Java 里的这个特性,所以我试着用了一下,现在懂了。它就像一种非常棒的访问控制机制,尤其是当你使用 DI 并想废弃某些东西时。当然还有模式匹配——这在处理事件驱动消息且负载形状发生变化时非常实用。

  4. timshel2

    Scala 正在空中挥拳庆祝呢

  5. panny

    我觉得有了 sealed 类型就不需要那些 switch 的 default 分支了。我没用编译器验证过,但我觉得那些是多余的。

  6. Larrikin

    Java 还在努力追赶 Kotlin

    https://kotlinlang.org/docs/sealed-classes.html

    当比较对象是 C++、Ruby 和 Python 时,我还能接受 Java。但在 Scala(似乎因为不加区分地引入特性而失败)之后,尤其是 Kotlin 出现后,我实在找不到理由再回头用 Java 了。

同日更多故事

2026-10-18