Java 多态

1. 无论向上转型还是向下转型,都需要有继承关系,否则编译器报错!

向上转型:子类型转向父类(自动类型转换) 

向下转型:父类型转向子类(强制类型转换,需要加强制类型转换符)

2. 什么是多态?

多态是同一个行为具有多个不同表现状态的能力。

多种状态,编译时是一种状态,运行时是另一种状态。

编译时,是静态绑定。编译器去找父类Animal中的move()方法,找到了,则编译通过,静态绑定成功;

运行时,是动态绑定。由于实际在堆内存中创建的对象是Cat对象,所以实际执行时会动态执行Cat的move()方法。(动态绑定是Java的默认行为,相当于C++的虚函数

上述过程,就是父类型引用指向子类型对象,向上转型,产生了多种形态(编译阶段绑定父类,运行阶段绑定子类)。

注:如果调用的是子类独有的方法,比如catch(),则不会通过编译,因为无法在父类中找到该方法。

3. 什么时候必须使用向下转型?

想要调用的方法是子类特有的,则需要强制类型转换(向下转型)。

向下转型有风险!如果失败,会抛出java.lang.ClassCastException

比如堆内存中创建的是Bird对象,用父类Animal类型引用a1接收,此时执行向下转型到Cat,会出错。

Animal a1=new Bird();
Cat c1=(Cat)a1;//出错

避免异常发生?使用instanceof来判断一个对象是不是属于该类型(运行阶段动态判断)

if(a1 instanceof Cat){//返回true或false
    Cat c1=(Cat)a1;
}

所以每当向下转型时,都要用instanceof进行类型判断,来避免ClassCastException。

4. JVM中多态运行情况

当执行 invokevirtual 指令(JVM方法调用指令,用于调用对象的实例方法)时,

(1) 先通过栈帧中的对象引用找到对象

(2) 分析对象头,找到对象的实际 Class

(3) Class 结构中有 vtable(标明这个类有几个方法),它在类加载的链接阶段就已经根据方法的重写规则生成好了

(4) 查表得到方法的具体地址

(5) 执行方法的字节码

 

原文地址:https://www.cnblogs.com/Kinghao0319/p/14405806.html