视频字幕
在Java中,协变与逆变是类型系统的重要概念。这些概念描述了当类型之间存在继承关系时,包含这些类型的复杂类型(如集合、数组)之间的子类型关系如何变化。Java的类型系统中有三种重要的类型关系:不变性、协变性和逆变性。让我们先看一个简单的类型继承层次,从Object到Animal到Cat再到Siamese猫,每个类型都是其上层类型的子类型。
不变性是Java泛型的默认行为。这意味着,即使Cat是Animal的子类型,List与List之间也没有子类型关系。这种设计保证了类型安全。例如,如果允许将List赋值给List变量,那么我们就可以向这个List添加Dog对象,但实际上底层是List,这会在运行时导致ClassCastException。因此,Java编译器会阻止这种赋值,比如'List animals = new ArrayList()'会产生编译错误。
协变意味着子类型关系被保留。在Java中,数组是天然协变的:如果Cat是Animal的子类型,那么Cat数组也是Animal数组的子类型。这允许我们将Cat数组赋值给Animal数组变量。然而,这种设计虽然方便,但也带来了运行时安全风险。在泛型中,Java通过上界通配符'? extends'实现了有限的协变。例如,List extends Animal>可以接收List或List的引用。使用这种方式,我们可以从列表中读取Animal类型的对象,但不能向其中添加任何对象(除了null),因为编译器无法确定具体的子类型。
逆变意味着子类型关系被反转。在Java泛型中,通过下界通配符'? super'实现逆变。如果Cat是Animal的子类型,那么List super Cat>可以接收List、List或List