假设我们有两个类:
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对象。
答案 0 :(得分:9)
Java编译器允许这样做,因为在Java数组中是协变的。即,可以说:
Superclass[] arr = new Subclass[3];
这允许编译xArr[0]= new X();
之类的代码。但是,JVM将在运行时捕获此错误并抛出ArrayStoreException
。它在运行时知道它实际上是Y[3]
,因此无法存储X
。
JLS, Section 4.10.3,确定数组类型的协方差:
以下规则定义了数组之间的直接超类型关系 类型:
如果S和T都是参考类型,那么S []> 1 T [] iff S> 1 T。
对象> 1对象[]
Cloneable> 1 Object []
java.io.Serializable> 1 Object []
如果P是基本类型,则:
对象> 1 P []
Cloneable> 1 P []
java.io.Serializable> 1 P []
这与不具有协变性的泛型相反 - 它们是不变的。即。
ArrayList<Superclass> list = new ArrayList<Subclass>(); // doesn't compile.