前提:
Cat 继承 Animal
继承关系如上所示,Animal类中有move()方法,Cat类中重写了move()方法。Cat类中有特有的CatchMouse()方法。
1.多态产生条件
无论是向上转型还是向下转型,两种类型之间必须要有继承关系,没有继承关系程序是无法编译通过的。
2.向上转型(自动类型转化)
Animal a1 = new Cat();
a1.move();
解释:
可以理解为猫是动物。父类型引用转向子类型对象,在程序编译阶段把a1当作Animal类型,所以调用方法的时候只能调用Animal类中有的方法,但是程序运行的时候看的是new出来的是什么,所以执行的是子类中的方法。 也就是调用的是父类的move()方法,执行的是子类的move()方法。所以在编译的时候看的是等号左边,运行的时候看的是等号右边。
编译阶段检查到a1这个引用的数据类型为Animal,由于Animal类中有move()方法。所以编译时通过了,这个过程称为静态绑定(编译阶段绑定),只有静态绑定成功了才有后续的运行。
在程序运行阶段,JVM堆内存当中真实创建的是Cat对象,所以在程序的运行阶段一定调用 的是Cat对象的move()方法,此时发生了程序的动态绑定(运行阶段绑定)。
如果将子类Cat中的move()方法注释掉再执行上面的两行代码的时候,a1调用的就是Animal中的move()方法,但实际上还是执行的Cat中的move()方法,因为Cat和Animal存在继承关系Cat将Animal的move()方法继承了。
3.向下转型(强制类型转化)
Animal a2=new Cat();
2.CatchMouse();
那么如果a2调用Cat类的特有方法CatchMouse()呢?能不能调用?结果是不能。因为在编译阶段编译器查到a2的类型是Animal类型,从Animal.class字节码文件中没有找到CatchMouse()方法,所以导致静态绑定失败,编译失败,所以不能调用。
a2是无法直接调用该方法的,因为a2的类型是Animal,Animal类中没有CatchMouse方法,要想去调用就应该将Animal类型转化为Cat类型,即向下转型。
所以说当调用的的方法是子类型特有的时候,必须进行向下转型。代码如下所示:
Animal a2=new Cat();
Cat c2=(Cat)a2;//将Animal类型转化为Cat类型
在下转型的时候为了避免出现java.lang.classCastException(类型转化异常,该异常总在下转型的时候发生)。在进行向下转型的时候应该使用instanceof运算来进行判断。代码如下所示:
if(a2 instanceof cat){
Cat c=(Cat)a2;
c.CatchMouse();
}
a2 instanceof cat如果为true则表示a2这个引用类型指向的是Cat,可以类型转化。如果是fasle则表示a2这个引用类型指向的不是Cat,就不可以类型转化。