本文例子取于<深刻理解java多态性>和<java提升篇(四)-----理解java的三大特性之多态>,分析 Java 继承链方法调用优先级以及执行流程。html
本文至关因而我对上面两篇文章的理解。java
public class A { public String show(D obj) { return ("A and D"); } public String show(A obj) { return ("A and A"); } } public class B extends A{ public String show(B obj){ return ("B and B"); } public String show(A obj){ return ("B and A"); } } public class C extends B{} public class D extends B{} public class Test { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println("(1)"+a1.show(b)); System.out.println("(2)"+a1.show(c)); System.out.println("(3)"+a1.show(d)); System.out.println("(4)"+a2.show(b)); System.out.println("(5)"+a2.show(c)); System.out.println("(6)"+a2.show(d)); System.out.println("(7)"+b.show(b)); System.out.println("(8)"+b.show(c)); System.out.println("(9)"+b.show(d)); } }
输出结果:this
(1)A and A (2)A and A (3)A and D (4)B and A (5)B and A (6)A and D (7)B and B (8)B and B (9)A and D
根据 Java 多态机制,继承链中对象方法的调用存在一个优先级:.net
this.method(O) -> super.method(O) -> this.method((super)O) -> super.method((super)O)code
上面两篇文章中都提到多态机制遵循的规则能够归纳为当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,可是这个被调用的方法必须是在超类中定义过的。htm
以上面的例子举例,A a = new B(); 就是超类对象引用变量 a 引用了子类 B 的对象,最终由 B 来决定调用谁的成员方法,但前提是这个方法即 show 方法必须在超类中定义过的。对象
在这里我把这两句话从新排序并解读:blog
- 当超类对象引用变量引用子类对象时,首先这个被调用的方法必须在超类中定义过 = 根据上面继承链对象方法调用优先级能够在超类中找到这个方法
- 被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法 = 判断子类是否重写了该方法,若是重写了直接调用子类的方法
简单来讲就是先根据优先级肯定目标方法,而后根据多态机制遵循的规则来决定调用子类仍是超类的成员方法。排序
下面开始分析例子中的九种状况。继承
(1)(2)(3) 的例子都不是超类对象引用变量引用子类对象的状况,因此在超类中找到方法后直接调用便可。
(1) a1.show(b)
(2) a1.show(c)
(3) a1.show(d)
(4)(5)(6) 都是超类对象引用变量引用子类对象的状况,因此在超类中找到方法后还要根据多态机制规则决定执行子类仍是超类的方法。
(4) a2.show(b)
(5) a2.show(c)
(6)a2.show(d)
至于(7)(8)(9)根据上面就能够推导出来。