Java多态对象的类型转换
周sir |
2015年3月30日 |
Java面向对象 |
0 条评论 | 1753
这里说的对象类型转换,只发生在有继承关系的类型之间。没有继承关系却强制转,运行时会抛 java.lang.ClassCastException。
继承链上,子类转成父类叫向上转型,父类转成子类叫向下转型。向上转型很常见:变量写成父类,实际引用子类,运行时靠动态绑定调用子类方法,也就是多态。若要做父类没有的事,再把引用转回子类,调用子类自己的方法,这就是向下转型。
一、向上再向下
class People {
void say() {
System.out.println("大家好,我是良民");
}
}
class Teacher extends People {
void say() {
System.out.println("大家好,我是一名老师");
}
void lecturing() {
System.out.println("我是一名老师,我的工作是讲课");
}
}
public class Demo {
public static void main(String[] args) {
People obj = new Teacher(); // 向上转型
Teacher tbj = (Teacher) obj; // 向下转型,实际对象本来就是 Teacher
}
}
不能把一个真正的父类对象强转成子类。原文说「必须先向上再向下」容易听成流程仪式,更准确的说法是:堆上实际类型必须已经是目标子类(或其子类),强制转换才安全。
public class Demo {
public static void main(String[] args) {
People obj = new People();
Teacher tbj = (Teacher) obj; // 运行时报 ClassCastException
}
}
二、转型后能调什么
指向子类的父类引用,编译期只能看见父类的方法和属性。子类多出来的方法(包括重载出来、父类没有的那一版)不能直接调。若子类覆盖了父类方法,调用时一定走子类(动态绑定)。
class People {
void say() {
System.out.println("大家好,我是良民");
}
}
class Teacher extends People {
void say() {
System.out.println("大家好,我是一名老师");
}
void say(String content) {
System.out.println(content);
}
void lecturing() {
System.out.println("我是一名老师,我的工作是讲课");
}
}
public class Demo {
public static void main(String[] args) {
People obj = new Teacher(); // 向上转型
// obj.lecturing(); // 不能调用:父类没有
// obj.say("我爱大家"); // 不能调用:这是重载出来的新签名
obj.say(); // 调用子类覆盖后的 say()
}
}
| 写法 |
实际对象 |
结果 |
| People obj = new Teacher() |
Teacher |
向上转型,安全;obj.say() 走子类 |
| (Teacher) obj |
必须是 Teacher |
才能调 lecturing()、say(String) |
| (Teacher) new People() |
People |
ClassCastException |
一句话总结:向上转型看编译类型、向下转型看实际对象;父类引用只能调父类签名,覆盖了的方法运行时仍走子类。
转载请注明来源:Java多态对象的类型转换
我是周sir,这是我的博客。致力于分享我学会的技术和优秀的文章。微信公众号 “周sir专栏” 欢迎大家关注。