密封类和密封接口sealed和permits关键字
1.sealed和permits
类和接口上可以添加sealed关键字,用来限定自己可以派生出哪些子类.换句话说,就是控制哪些子类可以继承或者实现自己,不允许其他类派生.
sealed class Base permits D1,D2{}
final class D1 extends Base{}
final class D2 extends Base{}
如上述代码所示,Base只允许D1和D2继承自己,其他类继承会报编译错误.
public sealed interface Ifc {
}
final class Imp1 implements Ifc{}
final class Imp2 implements Ifc{}
子类可以写在不同的文件中.如果子类和父类在同一个文件中,则不需要写permits语句.如上述代码所示,没有写permits关键字,也能正常编译.
2.non-sealed
sealed的子类只能通过final,sealed,non-sealed关键字来定义,如果不加final或者其他关键字,会编译报错.
non-sealed关键字表示允许未知的子类继承被修饰的类.
public sealed class Super permits Sub1, Sub2{
}
final class Sub1 extends Super{}
non-sealed class Sub2 extends Super{}
class Any1 extends Sub2{}
class Any2 extends Sub2{}
如上述代码所示,Sub2在没有permits关键字的情况下也可以被Any1和Any2继承;
3.record
record关键字是隐式的final,所以record也可以不加final继承密封类.
record类似于lombok的@Data注解,可以自己实现equals,toString,hashcode方法等.
用了record关键后,也可以继承密封类.
public sealed interface Employee permits CLevel, Programmer{
}
record CLevel(String type) implements Employee{}
record Programmer(String experience) implements Employee{}
4.getPermittedSubclasses方法
通过反射的getPermittedSubclasses方法我们可以直接获取被允许继承的子类,也就是permits关键字允许的类.
public sealed class Color permits Red,Green,Blue{
}
final class Red extends Color{}
final class Green extends Color{}
final class Blue extends Color{}
public class PermittedSubCLasses {
public static void main(String[] args) {
for(var p: Color.class.getPermittedSubclasses()) {
System.out.println(p.getSimpleName());
}
}
}
通过Class<T>类的getPermittedSubclasses方法可以直接获取子类的名称以及其他属性.