Java子类与父类之间的对象转换_java类继承总结一 父类类型与子类类型之间的转化问题(转)...

java类继承总结一 父类类型与子类类型之间的转化问题

本文将通过一个实例描述父类类型与子类类型之间的转化问题,这个很特殊的问题常常会导致一些潜在的危险,让你整整一个晚上都在调试程序以解决一个让人抓狂的java.lang.ArrayStoreException异常。

1. 子类数组的引用可以装换为超类数组的引用

2. 子类的引用child可以转换为父类的引用parent(这里假设parent是父类对象,child是子类对象),但却不可以通过 parent调用child的特有方法

ExpandedBlockStart.gifclass Employee{

6a9c071a08f1dae2d3e1c512000eef41.png  protected String name;

6a9c071a08f1dae2d3e1c512000eef41.png  protected long salary;

ExpandedSubBlockStart.gif  public Employee(String aName){

6a9c071a08f1dae2d3e1c512000eef41.png    this.name = aName;

ExpandedSubBlockEnd.gif  }

6a9c071a08f1dae2d3e1c512000eef41.png  

ExpandedSubBlockStart.gif  public void setSalary(long aSalary){

6a9c071a08f1dae2d3e1c512000eef41.png    this.salary = aSalary;

ExpandedSubBlockEnd.gif  }

6a9c071a08f1dae2d3e1c512000eef41.png  

ExpandedSubBlockStart.gif  public long getSalary(){

6a9c071a08f1dae2d3e1c512000eef41.png    return this.salary;

ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif

ExpandedBlockStart.gifclass Manager extends Employee{

6a9c071a08f1dae2d3e1c512000eef41.png  protected long bonus;

ExpandedSubBlockStart.gif  public Manager(String aName){

6a9c071a08f1dae2d3e1c512000eef41.png    super(aName);

ExpandedSubBlockEnd.gif  }

6a9c071a08f1dae2d3e1c512000eef41.png  

ExpandedSubBlockStart.gif  public void setBonus(long aBonus){

6a9c071a08f1dae2d3e1c512000eef41.png    this.bonus = aBonus;

ExpandedSubBlockEnd.gif  }

6a9c071a08f1dae2d3e1c512000eef41.png  

ExpandedSubBlockStart.gif  public long getSalary(){

6a9c071a08f1dae2d3e1c512000eef41.png    return super.getSalary()+this.bonus;

ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif

ExpandedBlockStart.gifpublic static void main(String[] args) {

6a9c071a08f1dae2d3e1c512000eef41.png    //注意,这时managers 和employees 引用的是同一个数组

6a9c071a08f1dae2d3e1c512000eef41.png    Manager[] managers = new Manager[10];

6a9c071a08f1dae2d3e1c512000eef41.png    Employee[] employees = managers;

6a9c071a08f1dae2d3e1c512000eef41.png    //(a)注意,下面三条语句是可以通过的,但运行时会抛出异常

6a9c071a08f1dae2d3e1c512000eef41.png    employees[0] = new Employee("Abel"); //运行时此处抛出java.lang.ArrayStoreException异常

6a9c071a08f1dae2d3e1c512000eef41.png    managers[0].setSalary(1000);

6a9c071a08f1dae2d3e1c512000eef41.png    managers[0].setBonus(500);

6a9c071a08f1dae2d3e1c512000eef41.png    //(b)这样的语句编译和运行都没有问题

6a9c071a08f1dae2d3e1c512000eef41.png    employees[0] = new Manager("Abel");

6a9c071a08f1dae2d3e1c512000eef41.png    employees[0].setSalary(1000);

6a9c071a08f1dae2d3e1c512000eef41.png    managers[0].setSalary(1000);

6a9c071a08f1dae2d3e1c512000eef41.png    managers[0].setBonus(500);

ExpandedBlockEnd.gif}

总结:

1. 在java中,对象变量是多态的,一个employee既可以引用Employee类型的实例,也可以引用子类Manager类型的实例,但一个manager不能引用一个Employee类型的实例,例如:

(1) Employee e = new Manager("Abel") 是合法的

(2)Manager   m = new Employee("Abel") 是不合法的

原因很容易理解,manager与employee是is-a的关系,任何一个manager都是一个emplpyee,如(1)所示,一个Employee类型的引用e可以引用Manager类型的实例,这意味着可以通过e使用Manager中任何继承自Employee的方法(注意,e不能使用Manager的特有方法,如e.setBonus(1000)是不合法的),Employee e = new Manager("Abel")的潜台词就是说,e从Employee的角度描述Manager,e就是一个Employee,不管e引用的是什么,编译器就把它当一个Employee来看。

2. 对于上面(a)的代码,不能运行是可以理解的, employees[0]虽然在声明时是Employee类型,但Employee[] employees = managers;规定了employees[i]指向的必须是Manager类型的实例,因此employees[0] = new Employee("Abel"); 这条语句必然会引发异常。

(a)处的代码employees[0] = new Employee("Abel");可以通过编译似乎也情有可原,因为employees声明的类型是Employee[], 那么employees[0]自然可以接受一个Employee类型的引用,但实际上

Employee[] employees = managers;赋值的过程中又规定了employees接受的必须是Manager类型,从上面的例子可以看出,运行的时候会做这样的检查,但编译的时候不会检查的这么深入,只会检查变量的声明类型,看来java编译器还不够智能啊 :)

3. 在实际编程的过程中,使用对象变量的多态性时一定要注意(尤其是使用数组的时候),否则编译通过,但运行报错,这个错误很可能让你调试一个晚上才能找出问题所在!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值