6

假设我们有 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 对象。

4

1 回答 1

9

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.
于 2013-10-28T19:40:31.190 回答