non-sealed 和 final 不能共存,因前者明确允许任意继承,后者禁止一切继承,语义互斥,编译器直接报错。

Java 中的 非密封类(non-sealed) 和 最终类(final) 不能直接结合使用——因为语义冲突:一个类若声明为 non-sealed,意味着它**明确允许被继承**;而 final 类则**禁止任何继承**。二者在语言层面互斥,编译器会报错。
为什么 non-sealed 和 final 不能共存?
non-sealed 是 Java 15 引入、Java 17 正式支持的密封类(sealed classes)机制中的修饰符,用于在 permits 列表中显式声明“哪些子类可以继承我”,并同时允许**未列出的其他类也继承我**(即开放继承)。它的存在前提是该类本身必须是 sealed 或其配套修饰符之一(sealed、non-sealed、final),且只能三选一。
final 类则彻底关闭继承通道,连编译期扩展都不允许。因此:
- 给类加上
non-sealed,等于说:“我欢迎任何人继承我”; - 给类加上
final,等于说:“谁都不许继承我”; - 两者逻辑矛盾,JVM 规范禁止这种写法,例如:
class A non-sealed final { ... } → 编译失败。
如何合理搭配 sealed / non-sealed / final?
在密封类体系中,这三者是同一层级的互斥修饰符,用于对直接子类的继承权限做精细控制。典型用法如下:
-
sealed:父类自身必须是sealed,并通过permits A, B, C限定可继承的子类列表; -
non-sealed:列在permits中的某个子类,用non-sealed表示“我虽被允许继承,但我自己不封禁,别人还能继承我”; -
final:列在permits中的某个子类,用final表示“我虽被允许继承,但到我为止,不再允许进一步继承”。
✅ 正确示例:
public sealed interface Shape permits Circle, Rectangle, Polygon { }
final class Circle implements Shape { } // ✅ 终止继承链
non-sealed class Rectangle implements Shape { } // ✅ 允许后续扩展,如 RoundedRect 继承 Rectangle
class Polygon implements Shape { } // ❌ 编译错误:未在 permits 中声明
想实现“部分开放 + 部分封闭”的设计,该怎么做?
这是密封类机制的核心价值。关键不是让一个类同时 non-sealed 和 final,而是通过组合不同修饰符,在类层次中分层管控继承权:
- 顶层接口或抽象类用
sealed定义合法子类型边界; - 具体实现中,对稳定、不可变的类型用
final(如Circle); - 对需要未来扩展的中间抽象类型,用
non-sealed(如Rectangle),再由下游模块定义其子类; - 所有子类必须显式出现在
permits列表中,否则编译不通过。
常见误区提醒
-
non-sealed只能用于被sealed父类明确许可的子类中,不能用于任意类; - 没有
sealed父类时,单独写non-sealed class X是非法的(Java 21 起才允许顶层non-sealed类,但此时它等价于普通类,无实际约束力); -
final类天然不可继承,所以它永远不可能有子类,也无需也不应加non-sealed; - 如果只是想“防止误继承”,优先考虑设计意图而非语法强制——
final是最强约束,sealed+final子类是结构化约束。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











