Java sealed classes 的隐藏陷阱
Java sealed classes and exhaustive pattern matching
Java 17 引入的 sealed classes 让模式匹配变得像 Haskell 一样优雅,编译器能自动检查是否覆盖了所有情况,无需 default 分支。但这背后有个致命陷阱:一旦你在公共 API 中暴露了 sealed 类型,新增子类型时,未重新编译的旧代码不会报错,而是等到运行时抛出 MatchException。这意味着所谓的“编译期安全”在跨模块场景下可能失效。作者认为,sealed classes 更适合组件内部使用,若强行用于公开 API,反而可能埋下运行时崩溃的隐患。
对于我而言,结论是 sealed 类型在组件内部实现中可能最有用,而当组件通过公共 API 向其他组件暴露时,其用处则较小。
HN 评论区
107- shepherdjerred
真没想到 Java 已经进步到这种程度了。不过我还是更喜欢 TypeScript,因为我做很多前端工作,倾向于在全栈中使用同一种语言。
话说回来,TypeScript 也能做穷尽模式匹配!https://github.com/gvergnaud/ts-pattern
- armchairhacker
Java 也有递归模式,还有(可能仍处于预览阶段)字面量模式:`switch (x) { case A(B(true, var c)) -> f(c); }`
- another_twist
我花了一段时间才习惯 sealed,当时也没太看出它的用处。但 AI 似乎很喜欢 Java 里的这个特性,所以我试着用了一下,现在懂了。它就像一种非常棒的访问控制机制,尤其是当你使用 DI 并想废弃某些东西时。当然还有模式匹配——这在处理事件驱动消息且负载形状发生变化时非常实用。
- timshel2
Scala 正在空中挥拳庆祝呢
- panny
我觉得有了 sealed 类型就不需要那些 switch 的 default 分支了。我没用编译器验证过,但我觉得那些是多余的。
- Larrikin
Java 还在努力追赶 Kotlin
https://kotlinlang.org/docs/sealed-classes.html
当比较对象是 C++、Ruby 和 Python 时,我还能接受 Java。但在 Scala(似乎因为不加区分地引入特性而失败)之后,尤其是 Kotlin 出现后,我实在找不到理由再回头用 Java 了。