必须用record+sealed构建领域模型:record确保模式匹配解构的结构可推导,sealed保障switch穷尽性检查;嵌套需逐层解构,when子句须无副作用且防null。

能大幅简化,但前提是领域模型得用 record + sealed 搭建,否则模式匹配的解构和穷尽性检查就断了一条腿。
record 必须带字段声明,不能只靠 getter
模式匹配解构依赖 record 的规范结构:字段名、类型、顺序必须明确可推导。如果你写的是普通 class,哪怕有 public final 字段或 lombok @Data,case Person(String name, int age) 这种写法直接编译失败。
- ✅ 正确:
public record Person(String name, int age) {} - ❌ 错误:
public class Person { public final String name; ... }(不支持解构) - ⚠️ 注意:
record里不能有额外字段(比如transient或计算字段),否则解构时会漏值或报错
sealed 接口/类是穷尽性检查的前提
当你要处理一个领域模型的多种变体(比如订单状态:Created、Paid、Shipped),只有用 sealed 显式列出所有子类型,switch 才能在编译期确认你没漏 case —— 否则必须保留 default,失去类型安全优势。
- ✅ 正确:
sealed interface OrderState permits Created, Paid, Shipped {} - ❌ 错误:用
interface OrderState+ 普通class实现 → 编译器无法验证穷尽性 - ⚠️ 注意:子类即使不显式写
non-sealed,只要不在permits列表里,继承就会被拒(Java 21 默认隐式密封)
嵌套解构要一层层对齐 record 结构
真实领域模型常有嵌套,比如 Order 包含 Address 和 List<item></item>。这时不能指望一次 case Order(...) 就把深层字段全拎出来;必须按 record 定义逐层展开,否则编译器不知道你在拆哪一层。
- ✅ 正确:
case Order(String id, Address addr, List<item> items) -> { ... }</item>,前提是Address和Item本身也是record - ❌ 错误:
case Order(String id, String addrCity, int itemQty) -> ...(编译不通过,字段路径不合法) - ⚠️ 注意:嵌套太深时,建议用
var先解一层,再在分支内用instanceof或二次switch继续拆,避免单行模式过长难读
守卫子句 when 要小心 null 和副作用
when 子句运行在模式匹配成功之后、分支执行之前,但它不是独立作用域——它能访问解构出的变量,但不能做耗时操作或修改状态,否则会影响 switch 表达式的纯函数语义。
- ✅ 安全:
case Person(String name, int age) when age >= 18 -> "adult" - ❌ 危险:
case Order(String id, Address a) when logToDB(id) -> ...(logToDB 是副作用方法,且可能抛异常打断匹配流程) - ⚠️ 注意:
when条件里访问的字段如果可能为null(比如Address是可选字段),必须先判空,否则 NPE 会发生在匹配阶段而非分支内
真正容易被忽略的是:模式匹配不是万能胶水,它只对“结构已知、边界清晰”的数据有效。一旦领域模型里混入 Map、JSON 字符串、泛型擦除后的 List<?>,就得退回传统方式处理——这时候强行套 record 模式反而增加维护成本。

















