密封类可以让我们更好的控制哪些类可以对我定义的类进行扩展。密封类可能对于框架或中间件的开发者更有用。在这之前一个类要么是可以被extends的,要么是final的,只有这两种选项。
密封类可以控制有哪些类可以对超类进行继承,在Java 17之前如果我们需要控制哪些类可以继承,可以通过改变类的访问级别,比如去掉类的public,访问级别为默认。比如我们在com.heiz.java11包中定义了如下的三个类:
package com.heiz.java11;
public abstract class Furit {
}
public class Apple extends Furit {
}
public class Pear extends Furit {
}
那么我们可以在另一个包com.heiz123.java11中写如下的代码:
private static void test() {
Apple apple = new Apple();
Pear pear = new Pear();
Fruit fruit = apple;
class Avocado extends Fruit {};
}
既可以定义Apple,Pear,也可以将apple实例赋值给Fruit,并且可以对Fruit进行继承。
如果我们不想让Fruit在com.heiz.java11包以外被扩展,在Java11版本中只能改变访问权限,去掉class的public修饰符。这样虽然可以控制被被继承,但是也会导致Fruit fruit = apple;也编译失败;在Java 17中通过密封类可以解决这个问题。
package com.heiz.java17;
public abstract sealed class Furit permits Apple,Pear {
}
public non-sealed class Apple extends Furit {
}
public final class Pear extends Furit {
}
在定义Furit时通过关键字sealed声明为密封类,通过permits可以指定Apple,Pear类可以进行继承扩展。
子类需要指明它是final,non-sealed或sealed的。父类不能控制子类是否可以被继承。
private static void test() {
Apple apple = new Apple();
Pear pear = new Pear();
// 可以将apple赋值给Fruit
Fruit fruit = apple;
// 只能继承Apple,不能继承Furit
class Avocado extends Apple {};
}