多态的运行特点
调用成员变量时:编译看左边,运行看左边
调用成员方法时:编译看左边,运行看右边
Fu f = new Zi();
//编译看左边的父类中有没有name这个属性,没有就报错
//在实际运行的时候,把父类name属性的值打印出来
System.out.println(f.name);
//编译看左边的父类中有没有show这个方法,没有就报错
//在实际运行的时候,运行的是子类中的show方法
f.show();
我们已经知道多态编译阶段是看左边父类类型的,如果子类有些独有的功能,此时多态的写法就无法访问子类独有功能了。
class Animal{
public void eat(){
System.out.println("动物吃东西!");
}
}
class Cat extends Animal{
public void eat() {
System.out.println("吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Test{
public static void main(String[] args){
Animal a = new Cat();
a.eat();
// a.catchMouse();//编译报错,编译看左边,Animal没有这个方法
// 必须强转后才能访问
Cat c = (Cat)a;
c.catchMouse();
}
}
强制转换异常 ClassCastException
转型的过程中,一不小心就会遇到这样的问题,请看如下代码:
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat(); // 调用的是 Cat 的 eat
// 向下转型
Dog d = (Dog)a;
d.watchHouse(); // 调用的是 Dog 的 watchHouse 【运行报错】ClassCastException
}
}
为了避免ClassCastException的发生,强转前最好先使用instanceof做一个判断
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat(); // 调用的是 Cat 的 eat
// 向下转型
if (a instanceof Cat){
Cat c = (Cat)a;
c.catchMouse(); // 调用的是 Cat 的 catchMouse
} else if (a instanceof Dog){
Dog d = (Dog)a;
d.watchHouse(); // 调用的是 Dog 的 watchHouse
}
}
}