在Java中,对象变量是多态的。
Employee e; e = new Employee(...); e = new Manager(...);//Manager继承Employee
这里的Employee类变量可以引用Employee类对象和任何一个Employee类的子类。
在P152的代码中
Manager boss = new Manager(...); Employee[] staff = new Employee[3]; staff[0] = boss; Employee boss = new Employee(...); Manager[] staff = new Manager[3]; staff[0] = boss;//错误!
boss是Manager类对象,staff数组是Employee类对象,所以staff可以和boss指向同一对象,且编译器将staff[0]看成Employee对象。如果是下面这段代码会报错,因为不是所有的雇员都是经理(类比double转换int可能会损失精度)。
向上转型一定是安全的,从小范围转向了大范围(从小范围的经理转向大范围的雇员,从小范围的猫转向大范围的动物,类似于从小范围的int转向大范围的double不会损失精度)。
对象的向上转型其实就是多态写法:
//格式:父类名称 对象名 = new 子类名称(); //右边创建了一个子类对象,把它当做父类看待使用 Employee Manager = new Employee() //创建了一个经理对象,把它当做雇员来看待
向下转型是一个【还原】的动作,但要保证对象一开始创建的时候 ,就是经理,才能由雇员向下转型为经理。(用instanceof关键字判断前面的对象是不是后面的类型)
String c = (String) staff[1]; //会产生编译错误,因为String不是Employee的子类
总结:
- 只能在继承层次内进行类型转换
- 将超类转换成子类(向下转型)之前,应该使用instanceof进行检查
- 类型转换不是一种好的做法,多态的对象向下转型是为了使用子类特有的方法,这种情况下应该检查超类的设计是否合理,也许重新设计超类并添加相应方法才是正确做法。尽量少用类型转换和instanceof