继承类数组的引用变量的行为

时间:2017-10-01 11:18:16

标签: java arrays inheritance

考虑到我有以下给定的类层次结构:

class parent{
  void parentMethod(){
    System.out.println("inside parent method");
  }
}

class child1 extends parent{
      void child1Method(){
        System.out.println("inside child method");
      }
}
class child2 extends parent{}
class grandchild1 extends child1{}

现在,如果我定义一个类似这样的数组:

parent[] p=new child1[4];

然后尝试以这种方式初始化它:

p[0]=new child1(); // works
p[1]=new parent(); //doesn't work
p[2]=new child2(); //doesn't work 
p[3]=new grandchild1(); //works

这使我得出结论,我可以将数组中的对象定义为类型为child1或从中继承的类。

然后如果我尝试访问这些方法:

p[i].ParentMethod();//works
p[i].Child1Method(); //doesn't work

这使我得出结论p [i]是父类型的引用。 这里发生了什么?

宣布

parent[] p=new child1[4];

我完全宣布了什么?

我只能将数组的各个元素声明为类型为child1及其子类,并且只能访问类parent的方法。我错过了什么概念?

2 个答案:

答案 0 :(得分:1)

parent[] p = new child1[4];

声明类型p的数组parent[]。所以,所有编译器都知道这个数组是一个只能包含父实例的数组。

您使用child1[]类型的数组初始化此变量。这在Java中是允许的,因为数组是协变的:子数组是父数组。但是,List<Parent>List<Child>等通用类型不允许这样做,因为List<Child>不是List<Parent>

因此,p具体,运行时类型为child1[]。这意味着,在运行时,该数组将只允许child1的实例存储在此数组中。尝试存储父项(由于声明的类型pparent[]),编译器允许这样做,将产生ArrayStoreException

再次注意,这种奇怪的设计并不存在于通用集合中,这通常应该是首选。

答案 1 :(得分:0)

下面:

parent[] p=new child1[4];

您正在创建一个长度为4的数组,该数组可以存储与child1兼容且具有new child1[4]部分的类型的对象。然后,您将该数组分配给类型为parent[]的变量。这在Java编译时是允许的。

然后,您将parent对象分配给数组中的一个元素。编译器认为这没关系,因为它认为p是一个parent的数组。但是在运行时,p实际上是一个child1的数组,它不能存储parent个对象。因此,将抛出ArrayStoreException

现在,当您尝试在child1中的元素上调用p的方法时,您不能。这是因为编译器认为pparent的数组。在parent中没有声明这样的方法,因此编译器会抱怨,但事实上,child对象存储在数组中。