阻止继承
正常情况下,只要某个class没有final修饰符,那么任何类都可以从该class继承。
从Java 15开始,允许使用sealed修饰class,并通过permits明确写出能够从该class继承的子类名称。
例如,定义一个Shape类:
public sealed class Shape permits Rect, Circle, Triangle {
...
}
上述Shape类就是一个sealed类,它只允许指定的3个类继承它。如果写:
public final class Rect extends Shape {...}
是没问题的,因为Rect出现在Shape的permits列表中。但是,如果定义一个Ellipse就会报错:
public final class Ellipse extends Shape {...}
// Compile error: class is not allowed to extend sealed class: Shape
原因是Ellipse并未出现在Shape的permits列表中。这种sealed类主要用于一些框架,防止继承被滥用。
sealed类在Java 15中目前是预览状态,要启用它,必须使用参数--enable-preview和--source 15。
向上转型
如果一个引用变量的类型是Student,那么它可以指向一个Student类型的实例:
Student s = new Student();
如果一个引用类型的变量是Person,那么它可以指向一个Person类型的实例:
Person p = new Person();
现在问题来了:如果Student是从Person继承下来的,那么,一个引用类型为Person的变量,能否指向Student类型的实例?
Person p = new Student(); // ???
测试一下就可以发现,这种指向是允许的!
这是因为Student继承自Person,因此,它拥有Person的全部功能。Person类型的变量,如果指向Student类型的实例,对它进行操作,是没有问题的!
这种把一个子类类型安全地变为父类类型的赋值,被称为向上转型(upcasting)。
向上转型实际上是把一个子类型安全地变为更加抽象的父类型:
Student s = new Student();
Person p = s; // upcasting, ok
Object o1 = p; // upcasting, ok
Object o2 = s; // upcasting, ok
注意到继承树是Student > Person > Object,所以,可以把Student类型转型为Person,或者更高层次的Object。