假设我们有 2 个类:
class X { }
class Y extends X { }
在 main 函数中创建一个数组:
Y[] yArr = new Y[3] // created Y's class objects array
X[] xArr = yArr;
xArr[0]= new X() // VALID. WHY?
怎么会这样??因为xArr
指的是Y[]
对象,据我了解,它不能创建 X 对象。
假设我们有 2 个类:
class X { }
class Y extends X { }
在 main 函数中创建一个数组:
Y[] yArr = new Y[3] // created Y's class objects array
X[] xArr = yArr;
xArr[0]= new X() // VALID. WHY?
怎么会这样??因为xArr
指的是Y[]
对象,据我了解,它不能创建 X 对象。
Java 编译器允许这样做,因为在 Java 中数组是协变的。即,可以说:
Superclass[] arr = new Subclass[3];
这允许编译诸如您的代码xArr[0]= new X();
。但是,JVM 会在运行时捕获此错误并抛出ArrayStoreException
. 它在运行时知道它确实是 a Y[3]
,因此不能存储X
.
JLS第4.10.3 节建立了数组类型的协方差:
以下规则定义了数组类型之间的直接超类型关系:
如果 S 和 T 都是引用类型,则 S[] >1 T[] iff S >1 T。
对象 >1 对象[]
可克隆 >1 个对象[]
java.io.Serializable >1 对象[]
如果 P 是原始类型,则:
对象 >1 P[]
可克隆 >1 P[]
java.io.Serializable >1 P[]
这与泛型相反,泛型不是协变的——它们是不变的。IE
ArrayList<Superclass> list = new ArrayList<Subclass>(); // doesn't compile.