密封类仅允许public或package-private修饰符,其许可子类访问性不得更宽松:public密封类的子类可为public或package-private(需同模块且包已导出),package-private密封类的子类必须同包且package-private。

Java 密封类(sealed)及其许可子类(permits 列表中的类)在访问修饰符使用上需满足严格兼容性要求,核心原则是:**子类的可访问性不能强于密封父类,且所有许可子类必须与父类在同一个编译单元(同一模块或未命名模块下)可被访问**。
密封类自身的访问修饰符限制
密封类必须显式声明访问修饰符,且仅允许 public 或 package-private(即不写修饰符):
-
不允许
private或protected—— 因为密封类需要被其许可子类继承,而private无法被继承,protected在跨包时对非子类开放,破坏密封语义。 -
public sealed class:许可子类可以是public或 package-private,但必须与父类在同一个模块中可访问(若在模块化系统中,需确保子类所在包被父类模块exports,且父类模块opens(如需反射)或未限制继承)。 - package-private sealed class:所有许可子类也必须是 package-private,且必须定义在**同一个包内**;跨包即使同模块也不合法。
许可子类的访问修饰符约束
许可子类的访问级别不能比密封父类更“宽”,且必须能实际继承父类:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 若密封类是
public,子类可为public或 package-private(只要在可访问范围内);但若子类设为public,它必须与父类在同一模块、且父类所在包已导出(exports)。 - 若密封类是 package-private,子类**必须也是 package-private**,且必须与父类在**同一包**;声明为
public会导致编译错误:“subclass is public but enclosing sealed class is not”。 - 子类不能使用
final(除非显式设计为终端)、non-sealed或sealed以外的修饰符;若要允许进一步扩展,必须用non-sealed显式开放。
模块系统下的额外兼容要求
在 JPMS(Java Platform Module System)中,仅语法合规还不够,还需满足模块可见性规则:
- 密封类所在的模块必须
exports其所在包给**定义许可子类的模块**(如果子类在不同模块中)。 - 若子类在另一个模块中,该模块需在
requires中声明依赖密封类所在模块。 - 模块无法限制“谁可以继承某个类”,因此
sealed的安全性依赖于permits列表 + 模块封装共同保障;漏配exports将导致编译失败:“class X is not visible”。
常见错误与检查要点
编译器会直接报错,典型提示包括:
- "sealed type cannot be private or protected" —— 密封类用了非法修饰符。
- "permitted subtype must have the same or more restrictive access" —— 子类访问性比父类宽松(如父类 package-private,子类 public)。
-
"class Y is not in the permits clause of sealed class X" —— 尝试继承但未列在
permits中。 - "package P is not exported to module M" —— 模块未导出,导致子类不可见。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










