java多态/重载方法——一个疑难代码引发的讨论

  直接上代码,看这个代码发现自己的基础有多差了。参考 http://www.cnblogs.com/lyp3314/archive/2013/01/26/2877205.html和http://hxraid.iteye.com/blog/428891 以及 《深入Java虚拟机》

  这个问题是java获取动态绑定最终的方法?涉及的知识有继承、多态、重载、方法调用的整合。

public class Poly {

    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(a1.show(b));
        System.out.println(a1.show(c));
        System.out.println(a1.show(d));
        System.out.println(a2.show(b));
        System.out.println(a2.show(c));
        System.out.println(a2.show(d));
        System.out.println(b.show(b));
        System.out.println(b.show(c));
        System.out.println(b.show(d));

    }
}

class A {
    public String show(D obj) {
        return ("A and D");
    }

    public String show(A obj) {
        return ("A and A");
    }
}

class B extends A {
    public String show(B obj) {
        return ("B and B");
    }

    public String show(A obj) {
        return ("B and A");
    }
}

class C extends B {
}

class D extends B {
}

  直接上结论:  

A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D

  摘抄结论:

  (1) 所有私有方法、静态方法、构造器及初始化方法<clinit>都是采用静态绑定机制。在编译器阶段就已经指明了调用方法在常量池中的符号引用,JVM运行的时候只需要进行一次常量池解析即可。 

      (2) 类对象方法的调用必须在运行过程中采用动态绑定机制。

           首先,根据对象的声明类型(对象引用的类型)找到“合适”的方法。具体步骤如下:

           ① 如果能在声明类型中匹配到方法签名完全一样(参数类型一致)的方法,那么这个方法是最合适的。

           ② 在第①条不能满足的情况下,寻找可以“凑合”的方法。标准就是通过将参数类型进行自动转型之后再进行匹配。如果匹配到多个自动转型后的方法签名f(A)和f(B),则用下面的标准来确定合适的方法:传递给f(A)方法的参数都可以传递给f(B),则f(A)最合适。反之f(B)最合适 。 

           ③ 如果仍然在声明类型中找不到“合适”的方法,则编译阶段就无法通过。 

           然后,根据在堆中创建对象的实际类型找到对应的方法表,查找方式同声明类型。

  挨个解读:

  •  System.out.println(a1.show(b));   //a1声明为A类型,A中不存在完全匹配的方法,对b向上转型为A,确定调用A.show(A)方法,a1实际类型为A类型,运行方法为A.show(A)方法。
  • System.out.println(a1.show(c)); //a1声明为A类型,A中不存在完全匹配的方法,对c向上转型为A,确定调用A.show(A)方法,a1实际类型为A类型,运行方法为A.show(A)方法。
  • System.out.println(a1.show(d));   //a1声明为A类型,A中存在完全匹配的方法,调用A.show(D)方法,a1实际类型为A类型,运行方法为A.show(D)方法。
  • System.out.println(a2.show(b));   //a2声明为A类型,A中不存在完全匹配的方法,对b向上转型为A,确定调用A.show(A)方法,a2实际类型为B类型,B类型覆盖了A.show(A),运行B.show(A)方法。
  • System.out.println(a2.show(c));   //a2声明为A类型,A中不存在完全匹配的方法,对c向上转型为A,确定调用A.show(A)方法,a2实际类型为B类型,B类型覆盖了A.show(A),运行B.show(A)方法。
  • System.out.println(a2.show(d));  //a1声明为A类型,A中存在完全匹配的方法,调用A.show(D)方法,a2实际类型为B类型,运行方法为B.show(D)方法。
  • System.out.println(b.show(b));    //b声明为B类型,B中存在完全一致的方法,调用B.show(B)方法,b实际类型为B类型,运行方法为B.show(B)。这是跟a2.show(b)最大的不同。
  • System.out.println(b.show(c));    //b声明为B类型,B中不存在完全一致的方法,对c向上转型为B,调用B.show(B)方法,b实际类型为B类型,运行方法为B.show(B)。
  • System.out.println(b.show(d));    //b声明为B类型,B中存在完全一致的方法,调用B.show(D)方法,b实际类型为B类型,运行方法为B.show(D)。
  总体上是jvm关于方法调用的机制不熟悉导致问题不懂,java基础还是得恶补。

你可能感兴趣的:(java多态/重载方法——一个疑难代码引发的讨论)