密封类通过permits白名单授权继承,要求显式列出同模块同包的允许子类,子类须用final/sealed/non-sealed明确策略,配合switch实现编译期穷尽检查,跨模块需模块系统协同导出与依赖声明。

用密封类控制继承,核心是“白名单授权”——不是禁止别人继承,而是只准你列出的几个类继承,一个都不能少,也不能多。
声明密封父类必须带 permits 列表
Java 17 要求密封类必须显式写出所有允许的直接子类,语法如下:
- 用 sealed 修饰类,并紧跟 permits 子句,后面跟类名(不带包路径),如
permits Dog, Cat - 所有被列在
permits中的类,必须和密封类在同一模块;单模块项目中通常要求同包 - 密封类本身可以是
abstract或具体类,但不能是final(否则矛盾)
每个子类必须明确自己的继承策略
被 permits 允许的子类,必须用以下三者之一修饰,编译器会强制检查:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
-
final:彻底封闭,不能再有子类(最常用,适合终端类型,如
Circle) -
sealed:自身也成密封类,需继续写
permits指定下级(适合中间抽象层,如Rectangle permits Square) - non-sealed:主动开放该分支,允许任意类继承(慎用,会削弱密封性,且 switch 穷尽检查失效)
配合 switch 实现编译期穷尽检查
密封类真正发挥威力的地方,在于让 switch 表达式能静态确认“已覆盖所有可能子类”:
- 变量类型必须精确是密封类本身,例如
Shape s = ...,不能是Object s或泛型擦除后的类型 - 所有
case必须对应permits中列出的每一个直接子类(或其模式变量),缺一个就编译报错 - 如果某个子类用了
non-sealed,JVM 不再保证穷尽性,编译器将拒绝启用 exhaustive 检查
模块化项目要注意可见性
跨模块使用时,仅靠 permits 不够,还需模块系统配合:
- 密封类所在模块需在
module-info.java中exports对应包 - 子类所在模块需
requires密封类模块,且若子类要被外部访问,可能还需opens - 漏掉任一模块声明,即使
permits正确,也会报 “class X is not allowed to extend sealed class Y”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










