为什么超类的实例可以放入子类数组?

时间:2013-10-28 19:37:25

标签: java inheritance

假设我们有两个类:

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对象。

1 个答案:

答案 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.