java核心技术一书中一个关于数组的例子不理解,请教大家

Mr_Sky 发布于 2014/06/13 17:20
阅读 309
收藏 3

Person是Employer的父类,Employer有个新方法setBonus,代码如下

Employer[] emprs ={new Employer("张三"),new Employer("李四")};
    		
Person[] ps =emprs;
    		
    
ps[0] = new Person("小明");//运行时报错ArrayStoreException
    		
emprs[0].setBonus(2000);



书中给出的解释是要保持数组中的元素对象类型一致,
我不理解的是ps定义的元素的类型是Person,为什么在这里不能ps[0] = new Person("小明"),ps[0]不是只是对new Person("小明")的一个引用吗?他又不是Employer类型,我去给它赋值为Person类型有什么不可?

ps以上代码如果不用数组的形式,是正常的。

可能我以上的理解本身有错误,请大家指教指正。


加载中
0
夜游长空
夜游长空

首先,emprs是一个Employer对象的数组。其中是不可以添加Person类型的对象的。这点你应该明白吧。

第二,虽然ps的定义方式是Person[],但是它实际上是emprs的引用(Person[] ps =emprs;)。之所以ps可以作为emprs的引用,你应该也可以理解吧。

第三,既然ps是emprs的引用,所以ps所引用的数组仍然是emprs,而这个数组是一个Employer对象的数组,自然是不能将第一个元素替换为一个Person对象的。

从理论上来讲,一个数组并不会因为它的引用类型的改变而改变其中元素(对象)的类型,所以,即使是用ps来引用emprs,这个数组仍然是一个Employer作为元素的数组。如果想将这个数组转换为Person类型的,需要使用额外的代码。比如,Arrays.asList(emprs).toArray(new Person[emprs.length]);

Mr_Sky
Mr_Sky
现在搞清楚了。我是把ps和ps[0]搞混淆了。ps[0]只是ps中的一个元素,真正的引用其实是ps。ps在之前已经设定为了存放Employer对象,所以现在其中的一个元素要变为父对象Person是不可以的,要改,只能改为Employer或者其子类对象。
0
流水逃兵
流水逃兵
emprs的类型是[LEmployer,所以不能存储Person对象,如果第一行这样写是可以的:Person[] emprs ={new Employer("张三"),new Employer("李四")};这时emprs的类型是[LPerson。
Mr_Sky
Mr_Sky
我理解ps[0]不是一个指向new Person("小明")的引用吗? 而且之前对ps的申明就是Person类型 为什么这里把它再指向new Person("小明")就不行了。是我哪里的基础概念错了吗?
0
御风林海
御风林海
Person ps指向的是他的子类,那么赋值之后,Person里面的元素就是 Employer,而不是Person,你再new Person,他就会做初始化操作(重新分配内存地址),此时发现里面的内存地址已经是Employer,所以就出错,这就好比你做了 Employer E=new Person(),肯定出错,因为子类是父类的延伸,子类拥有父类的遗传的东西,但父类不一定有子类有的东西。说得不好,也不知道这样理解正确没有。希望你明白我在说什么。
0
l
leohp

这个涉及到Java 对象的内存模型,去google 这个关键字,就明白了。

Person[] ps = emprs;
 这行代码就是用emprs 的内存模型把ps 初始化了,之后所有的ps 所引用的对象必须满足emprs 及emprs 子类的内存模型。
Person是Employer的父类
试考虑,如果这句话说,Person 是Employer 的接口呢?你自然就顺利成章的接受了不能new Person("name") 了吧。前面几位说的有点绕,但道理是一样的。
l
leohp
回复 @Mr_Sky : 是的,但那样的话,问题的实质就有点变化了。Java 是强类型语言,Employee[], Person[], Employee, Person 就是四个不同的类型; 另外,Employee 是Person 的父类,但 Employee[] 不是 Person[] 的父类哦,这点就是你说的“关键”的本质所在 :)
Mr_Sky
Mr_Sky
有一个关键是这里用的是数组,如果问题中的代码不用数组,那么运行是正常的
返回顶部
顶部