java类继承总结一 父类类型与子类类型之间的转化问题(转)
2011-06-18 12:22
330 查看
本文将通过一个实例描述父类类型与子类类型之间的转化问题,这个很特殊的问题常常会导致一些潜在的危险,让你整整一个晚上都在调试程序以解决一个让人抓狂的java.lang.ArrayStoreException异常。
1. 子类数组的引用可以装换为超类数组的引用
2. 子类的引用child可以转换为父类的引用parent(这里假设parent是父类对象,child是子类对象),但却不可以通过 parent调用child的特有方法
class Employee...{
protected String name;
protected long salary;
public Employee(String aName)...{
this.name = aName;
}
public void setSalary(long aSalary)...{
this.salary = aSalary;
}
public long getSalary()...{
return this.salary;
}
}
class Manager extends Employee...{
protected long bonus;
public Manager(String aName)...{
super(aName);
}
public void setBonus(long aBonus)...{
this.bonus = aBonus;
}
public long getSalary()...{
return super.getSalary()+this.bonus;
}
}
public static void main(String[] args) ...{
//注意,这时managers 和employees 引用的是同一个数组
Manager[] managers = new Manager[10];
Employee[] employees = managers;
//(a)注意,下面三条语句是可以通过的,但运行时会抛出异常
employees[0] = new Employee("Abel"); //运行时此处抛出java.lang.ArrayStoreException异常
managers[0].setSalary(1000);
managers[0].setBonus(500);
//(b)这样的语句编译和运行都没有问题
employees[0] = new Manager("Abel");
employees[0].setSalary(1000);
managers[0].setSalary(1000);
managers[0].setBonus(500);
}
总结:
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. 在实际编程的过程中,使用对象变量的多态性时一定要注意(尤其是使用数组的时候),否则编译通过,但运行报错,这个错误很可能让你调试一个晚上才能找出问题所在!!
1. 子类数组的引用可以装换为超类数组的引用
2. 子类的引用child可以转换为父类的引用parent(这里假设parent是父类对象,child是子类对象),但却不可以通过 parent调用child的特有方法
class Employee...{
protected String name;
protected long salary;
public Employee(String aName)...{
this.name = aName;
}
public void setSalary(long aSalary)...{
this.salary = aSalary;
}
public long getSalary()...{
return this.salary;
}
}
class Manager extends Employee...{
protected long bonus;
public Manager(String aName)...{
super(aName);
}
public void setBonus(long aBonus)...{
this.bonus = aBonus;
}
public long getSalary()...{
return super.getSalary()+this.bonus;
}
}
public static void main(String[] args) ...{
//注意,这时managers 和employees 引用的是同一个数组
Manager[] managers = new Manager[10];
Employee[] employees = managers;
//(a)注意,下面三条语句是可以通过的,但运行时会抛出异常
employees[0] = new Employee("Abel"); //运行时此处抛出java.lang.ArrayStoreException异常
managers[0].setSalary(1000);
managers[0].setBonus(500);
//(b)这样的语句编译和运行都没有问题
employees[0] = new Manager("Abel");
employees[0].setSalary(1000);
managers[0].setSalary(1000);
managers[0].setBonus(500);
}
总结:
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. 在实际编程的过程中,使用对象变量的多态性时一定要注意(尤其是使用数组的时候),否则编译通过,但运行报错,这个错误很可能让你调试一个晚上才能找出问题所在!!
相关文章推荐
- java类继承总结一 父类类型与子类类型之间的转化问题
- java类继承总结一 父类类型与子类类型之间的转化问题
- java类继承总结一 父类类型与子类类型之间的转化问题
- 当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行。
- JAVA中子类是否可以可以继承、重写父类的静态方法--总结
- Java子类继承父类,构造方法的执行顺序问题
- 子类继承父类时,创建对象,构造方法的调用问题
- private继承导致子类不能转化为父类
- 子类继承父类(父类和子类里:块、静态块、构造和方法覆写)之间调用顺序
- 一、获取子类DAO继承父类DAO的泛型参数类型的Class对象
- Java中子类继承父类方法应该注意的问题
- java中子类继承父类程序执行顺序问题
- 关于继承及父类引用指向子类的一些总结
- java中子类继承父类程序执行顺序问题
- 有关继承,实现接口,子类,实例化对象之间总结
- java继承实质、父类引用指向子类对象(多态)、声明时类型、运行时类型
- [Unity&继承&序列化&JSON]在JSON数据中,子类继承父类问题
- 当子类继承父类,其子类和父类中静态代码块,构造代码块,无参构造之间的输出顺序
- 关于继承与构造函数重载的问题(初始化子类构造函数中的父类对象)求解答。。。
- C++中子类和父类之间的相互转化