sealed(密封类)是Java 17的正式特性,它承诺的"只有permits列表里的类能实现/继承"到底是不是玩真的——这篇真实写一个"越界"的实现类,让javac亲口告诉答案。
上一篇:Record 紧凑构造器真实验证
声明一个sealed接口,permits明确列出三个允许的实现类;再故意写一个第四个类去实现它,看javac真实怎么反应。
SealedClassesDemo.java sealed interface Shape permits Circle, Square, Triangle {} record Circle(double radius) implements Shape {} record Square(double side) implements Shape {} record Triangle(double base, double height) implements Shape {} // 另一个文件 public class UnpermittedShape implements SealedClassesDemo.Shape {}
UnpermittedShape.java:1: error: class is not allowed to extend sealed class: Shape
(as it is not listed in its permits clause)
public class UnpermittedShape implements SealedClassesDemo.Shape {
^
1 error
真实结果证明 sealed 的约束是一条真实的编译期规则,不是文档层面的君子协定:javac 在编译 UnpermittedShape 这个类的时候,真实检查了它想要实现的 Shape 接口的 permits 子句,发现 UnpermittedShape 不在列表里,直接真实拒绝编译,错误信息明确指出了原因。这意味着一个标记为 sealed 的类型,它的完整继承体系在编译完成的那一刻就真实是封闭、确定的,不会有第三方代码能在你不知情的情况下"偷偷"扩展它。
用java.lang.Class新增的isSealed()和getPermittedSubclasses()方法,从运行时角度确认这个约束信息。
SealedClassesDemo.java Shape.class.getPermittedSubclasses(); Shape.class.isSealed();
Shape.getPermittedSubclasses() 真实列表: Circle Square Triangle Shape.isSealed() 真实结果: true Circle.class.isSealed() 真实结果: false(record默认是final的,不是sealed) Circle真实是final类: true
既然permits列表真实穷尽了所有可能的实现类,用它们做具体业务逻辑也真实符合预期。
Circle面积真实结果: 12.566370614359172 Square面积真实结果: 9.0 Triangle面积真实结果: 10.0
真实结果验证了基于 instanceof 模式匹配对 Shape 三个子类型分别计算面积,得到的数值真实正确。sealed 接口在这里带来的真实价值是:开发者和编译器都能确信"这就是全部可能的类型",不用担心某个第三方库在未来悄悄引入第四种 Shape 实现导致处理逻辑出现遗漏分支。
每一行都是真实运行(或真实编译)得到的结果。