跳转至

sealed:封闭类与接口#

版本信息

  • 最低 JDK:17(15/16 预览 → 17 正式)
  • JEPJEP 409

为什么需要#

JDK 8 里谁能 extends/implements 你的类是开放的,无法穷举所有子类,于是 switch/if-else 不得不写 default 兜底,类型系统帮不上忙。sealed 让你显式声明允许的子类型,编译器由此能做穷尽性检查。

语法#

package com.javamodern.sealed;

// sealed:限定哪些类型可以实现/继承
public sealed interface Shape permits Circle, Square { // (1)
    double area();
}
  1. :material-lightbulb: sealed interface Shape permits Circle, Square 限定只有 CircleSquare 可实现;它们自己必须声明为 finalsealednon-sealed(record 隐式 final)。

与 JDK 8 旧写法对比#

interface Shape { double area(); }
// 任何类都能 implements Shape,switch 永远需要 default
sealed interface Shape permits Circle, Square { double area(); }
// 编译器知道只有 Circle/Square;配合 switch 模式匹配(JDK 21)可省去 default

底层原理#

sealed 在字节码层面通过 PermittedSubclasses 属性记录允许的子类;JVM 在加载时校验实现者确实在白名单内,类型系统的约束贯穿编译期与运行期。

graph TD
    S["sealed interface Shape"] -->|permits| C[Circle]
    S -->|permits| Q[Square]
    C -.final.- R["record,隐式 final"]
    Q -.final.- R
    style S fill:#bbdefb

常见坑 / 最佳实践#

  • 子类型必须与密封类在同一模块/包,或显式声明(final/sealed/non-sealed)。
  • sealed + record + pattern matching 是"代数数据类型"三件套,建模领域模型时格外好用。
  • 别为用而用:开放扩展点(如框架 SPI)不该 sealed。

小结#

sealed 给类型系统加上"穷尽性"能力,是后续 switch 模式匹配(JDK 21) 的基石。

参考#