用sealed接口或抽象类搭配record类是最直接安全的方式:前者限定穷尽子类型,后者保证不可变数据与值语义,配合模式匹配实现编译期穷尽检查与安全解构。

用密封类(sealed)搭配记录类(record)是最直接、最安全的方式。它让类型结构封闭、数据不可变、语义清晰,且编译期就能验证完整性。
用 sealed 接口或抽象类定义封闭类型族
领域模型中常有一组互斥但穷尽的变体,比如订单状态(Pending、Shipped、Cancelled)、表达式节点(Number、Add、Multiply)或几何图形(Circle、Rect、Triangle)。这时不应让任意类实现某个接口,而应明确限定合法子类型。
- 声明为 sealed interface 或 sealed abstract class,并用 permits 列出所有允许的实现类
- 每个 permitted 类必须显式标注为 final、sealed 或 non-sealed;对不可变领域对象,通常选 final
- 所有子类型需与密封父类型在同一个模块(或同一包中,若未启用模块系统)
用 record 实现具体不可变变体
每个子类型若仅承载数据、无复杂行为,就该用 record —— 它自动提供 final 字段、公共访问器、值语义的 equals/hashCode/toString,且禁止修改状态。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- record 的字段默认是 final,构造后无法更改,天然满足不可变性要求
- record 可实现 sealed 接口或继承 sealed 抽象类,语法简洁,无样板代码
- 若某变体需要校验逻辑(如三角形三边有效性),可用普通 final 类替代 record,但仍保持不可变字段和无 setter
配合模式匹配提升类型安全与可维护性
密封+记录的组合让 switch 表达式能做穷尽检查:编译器确保你覆盖了所有 permitted 子类型,漏写会报错,避免运行时 MissingCaseError。
- switch (shape) { case Circle c -> ...; case Rectangle r -> ...; } 编译器知道只有这两个分支合法
- instanceof 模式匹配也能直接解构 record 字段:if (obj instanceof Circle c && c.radius() > 10)
- 这种写法比传统 if-else + getClass() + 强转更安全、更简洁、更易重构
避免常见设计偏差
不可变不等于“不能有行为”,也不等于“必须全用 record”。关键在于职责分离和边界控制。
- 不要为了复用而让工具类或服务类被继承 —— 工具类适合静态方法,服务类适合组合
- 不要用继承表达“has-a”关系(如 User 有 Address),应直接持有一个 record 类型的 Address 字段
- 若未来可能新增变体(如支持新图形类型),需评估是否真要开放扩展 —— 若是内部领域模型,封闭更利于稳定;若是公共 API,可将部分子类设为 non-sealed 并谨慎文档化
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










