non-sealed 仅允许 permits 列表中直接声明的子类自主开放继承,且须显式标注 final/sealed/non-sealed;它不改变父类密封性,作用域限于自身,受模块与包可见性约束。

用 non-sealed 开放特定子类的继承权限,关键在于“精准授权”——它只对 permits 列表中的**直接子类**生效,且必须由该子类自己声明,不能跳级、不能批量、不能跨模块。
non-sealed 只能用在被 permits 明确列出的子类上
密封类通过 permits 锁定可继承范围,而 non-sealed 是这个范围内某一个子类的“自我解封”动作。它不是父类给的权限,而是子类主动选择开放自身继承链。
- 如果某个类没出现在
permits列表里,哪怕加了non-sealed,也无法继承密封类(编译报错) - 出现在
permits中的子类,必须明确选一种修饰符:final、sealed或non-sealed;不写任何修饰符会编译失败 - 例如:若
Person的permits Student, Teacher,那么只有Student和Teacher能声明non-sealed,其他类如Visitor连定义都非法
non-sealed 不影响兄弟类或祖父类的密封性
non-sealed 的作用域非常局部:它只解除当前类自身的继承限制,不会让它的父类、兄弟类、子类自动获得额外权限。
-
Teacher extends Person声明为non-sealed,只表示MathTeacher、PhysicsTeacher等可以继承Teacher,但不影响Student是否可被继承 -
Person仍是密封的,所有新增子类仍必须出现在它的permits列表中;non-sealed Teacher并不会让Person变成非密封 - 孙子类(如
MathTeacher)是否可被进一步继承,取决于它自己是否声明non-sealed,与Teacher的状态无关
实际设计时的典型配合模式
常见组合体现的是“分层管控”思想:顶层密封确保主干稳定,中间层用 non-sealed 预留扩展点,末端用 final 固化具体实现。
-
框架基类:用
sealed+permits定义核心能力边界(如Handler允许AuthHandler、LogHandler) -
可插拔模块:将
LogHandler设为non-sealed,允许业务方自定义CloudLogHandler、LocalLogHandler -
最终实现:业务方的具体子类通常用
final,避免被意外再继承,保证行为可预期
注意模块和包的可见性约束
即使语法正确,non-sealed 子类能否被继承还受模块系统限制:
- 所有
permits列出的子类,必须与密封类位于同一模块(或默认模块下同一包) - 如果密封类在模块 A,子类在模块 B,即使加了
non-sealed,模块 B 也必须在module-info.java中opens对应包,否则继承仍被拒绝 - 非模块化项目中,只要在同一个包内,
non-sealed就可被同包其他类继承










