黑马程序员技术交流社区

标题: 关于 方法 调用优先级 [打印本页]

作者: 黄鸿达    时间: 2013-1-25 01:59
标题: 关于 方法 调用优先级
本帖最后由 张向辉 于 2013-1-25 13:46 编辑

这个在网上看到,红字是引用,做了以后发现自己做错了不少。看完他的讲解之后,用了他所讲解的方法去做,但是还是个不太懂流程,就是第5个
     System.out.println(a2.show(c));   ⑤  根据this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
1、类A show(c) ----------------------- NO
2、SUPER类A show(c)  ----------------------- NO
3、类A show((super)c)即B ----------------------- NO
4、 SUPER类A show((super)c)即B -----------------------  NO
然后又是怎么找的,我就不知了,求解答

还有1个
还是不太懂为什么那个this ,A a2=new B();this为什么不是指向类B,不是B类这个对象在使用咩?



(一)相关类

    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 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));    ⑨     

(三)答案

①   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

实际上这里涉及方法调用的优先问题 ,优先级由高到低依次为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。以此准则,推算下结果的思路。

a2是一个引用变量,类型为A,它引用的是B的一个对象。记得在core java中有过这么一个定论:一个对象有哪些方法,是由声明的类型决定,而不是实例化的类型决定,这个没有疑问,用eclipse看a2的方法确实只看到show(A obj),并没有show(B obj)。再结合上面说的顺序,this为a2,于是它到类A里面找show(B obj)方法,没有找到,于是到A的super(超类)找,而A没有超类,因此转到第三优先级this.show((super)O),(super)O即(super)B即A,因此它到类A里面找show(A obj)的方法,类A有这个方法,但是,按照红字的准则,调用谁的成员方法是由被引用对象的类型来决定,由于a2引用的是类B的一个对象,B覆盖了A的show(A obj)方法,因此最终锁定到类B的show(A obj),输出为"B and A”。

当然,另一种思路可以直接按照准则去找,a2是一个引用变量,类型为A,它引用的是B的一个对象,因此这句话的意思是由B来决定调用的是哪个方法。因此应该调用B的show(B obj)从而输出"B and B”才对。但是请注意红字的后半部分,这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。B里面的show(B obj)在超类A中有定义吗?没有!那就更谈不上被覆盖了。它在类A中找到了show(A obj),如果子类B没有覆盖show(A obj)方法,那么它就调用A的show(A obj)(由于B继承A,虽然没有覆盖这个方法,但从超类A那里继承了这个方法,从某种意义上说,还是由B确定调用的方法,只是方法是在A中实现而已)。现在子类B覆盖了show(A obj),因此它最终锁定到B的show(A obj),所以输出"B and A”。


作者: 杨政    时间: 2013-1-25 03:42
本帖最后由 杨政 于 2013-1-25 03:45 编辑

a2.show(c):
先得明确a2的类型是A(声明类型是A)。所以a2只能调用A中的方法和A子类B中重写的方法,就两个
public String show(D obj)...{  
                    return ("A and D");  
             }   
public String show(A obj)...{  
                    return ("B and A");  
             }   

a2.show(c),c的类型为C,是A的extend类,故5调用的是
public String show(A obj)...{  
                    return ("B and A");  
             }   
输出结果 B and A
作者: 刘军亭    时间: 2013-1-25 08:19
A a2=new B(); 创建了A类型B的对象,在内存中是有一个A类型的引用,指向了B类型的一个对象。

  System.out.println(a2.show(b));   ④  //B and A
  System.out.println(a2.show(c));   ⑤ //B and A

用a2.show(b)时候,因为b对象在传递的时候会提升为A类型,所以就会调用  
public String show(A obj)...{  
                    return ("B and A");  
             }   
作者: 梁俊    时间: 2013-1-25 10:10
本帖最后由 梁俊 于 2013-1-25 10:12 编辑

  1. public class Test7 {
  2.         public static void main(String[] args) {
  3.                  A a1 = new A();  
  4.          A a2 = new B();  
  5.          B b = new B();  
  6.          C c = new C();   
  7.          D d = new D();   
  8.         //a1有两个方法show(D obj),show(A obj)
  9.          System.out.println(a1.show(b));  //A类没有带B的参数,B继承自A,所以调用A类的show(A obj)函数
  10.          System.out.println(a1.show(c));  //B类没有带C的参数,C继承自B,A类没有带B的参数,B继承自A,所以调用A类的show(A obj)函数  
  11.          System.out.println(a1.show(d));  //A类有带D的参数,所以调用A类的show(D obj)函数   
  12.          //a2有两个方法show(D obj),所以调用B类的show(A obj)方法,输出为B and A
  13.          //show(A obj)方法覆盖父类方法,所以调用Blei
  14.          System.out.println(a2.show(b));  //a2没有带B的参数,B继承自A,所以调用B类的show(A obj)函数
  15.          System.out.println(a2.show(c));  //a2没有带C的参数,C继承自B,B类没有带B的参数,B继承自A,所以调用B类的show(A obj)函数
  16.          System.out.println(a2.show(d));  //a2有带D的参数 ,所以调用B类的show(D obj)函数,也就是A类的show(D obj)函数
  17.          //b有有三个方法show(D obj),show(B obj),show(A obj)
  18.          //show(A obj)方法覆盖父类方法,所以调用B类的show(A obj)方法,输出为B and A
  19.          System.out.println(b.show(b)); //b有带B的参数,所以调用B类的show(B obj)函数
  20.          System.out.println(b.show(c)); //b没有带C的参数,C继承自B,B类有带B的参数,所以调用B类的show(B obj)函数
  21.          System.out.println(b.show(d)); //b有带D的参数 ,所以调用B类的show(D obj)函数,也就是A类的show(D obj)函数
  22.         }
  23. }

  24. class A {  
  25.          public String show(D obj){  
  26.                 return ("A and D");  
  27.          }   
  28.          public String show(A obj){  
  29.                 return ("A and A");  
  30.          }   
  31. }   
  32. class B extends A{  
  33.          public String show(B obj){  
  34.                 return ("B and B");  
  35.          }  
  36.          public String show(A obj){  
  37.                 return ("B and A");  
  38.          }   
  39. }  
  40. class C extends B{}   
  41. class D extends B{}  

复制代码

作者: 梁俊    时间: 2013-1-25 10:12
本帖最后由 梁俊 于 2013-1-25 10:14 编辑

//a1有两个方法show(D obj),show(A obj)
         System.out.println(a1.show(b));  //A类没有带B的参数,B继承自A,所以调用A类的show(A obj)函数
         System.out.println(a1.show(c));  //B类没有带C的参数,C继承自B,A类没有带B的参数,B继承自A,所以调用A类的show(A obj)函数  
         System.out.println(a1.show(d));  //A类有带D的参数,所以调用A类的show(D obj)函数   
         //a2有两个方法show(D obj),所以调用B类的show(A obj)方法,输出为B and A
         //show(A obj)方法覆盖父类方法,所以调用Blei

         System.out.println(a2.show(b));  //a2没有带B的参数,B继承自A,所以调用B类的show(A obj)函数
         System.out.println(a2.show(c));  //a2没有带C的参数,C继承自B,B类没有带B的参数,B继承自A,所以调用B类的show(A obj)函数
         System.out.println(a2.show(d));  //a2有带D的参数 ,所以调用B类的show(D obj)函数,也就是A类的show(D obj)函数
         //b有有三个方法show(D obj),show(B obj),show(A obj)
         //show(A obj)方法覆盖父类方法,所以调用B类的show(A obj)方法,输出为B and A

         System.out.println(b.show(b)); //b有带B的参数,所以调用B类的show(B obj)函数
         System.out.println(b.show(c)); //b没有带C的参数,C继承自B,B类有带B的参数,所以调用B类的show(B obj)函数
         System.out.println(b.show(d)); //b有带D的参数 ,所以调用B类的show(D obj)函数,也就是A类的show(D obj)函数
作者: 黄锦成    时间: 2013-1-25 10:15
这个主要弄清楚  : 父类  对象名 = new  子类(); 是调用哪里的方法,其他的如 :
子类  对象名 = new  子类(); 这个一下子就能看出来
作者: 黄金龙    时间: 2013-1-25 10:46
本帖最后由 黄金龙 于 2013-1-25 10:55 编辑

(一)相关类

    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(D obj)...{  
                    return ("A and D");  
             }  //这里我把继承的写了出来方便观看
             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 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));   ①   //这里就去A类找去...发现没 B 类型 所以会向上转型为A 所以就是结果 A and A
            System.out.println(a1.show(c));   ② //这里就去A类找去...发现没 C 类型 所以会向上转型为A 所以就是结果 A and A
            System.out.println(a1.show(d));   ③  //这里就去A类找去...发现 D 类型 所以就是结果 A and D
            System.out.println(a2.show(b));   ④  //这里是多态B类找...发现没 A父类B 类型的 所以会向上转型为A 但是B类复写了这方法所以就是结果 B and A
            System.out.println(a2.show(c));   ⑤ //这里是多态B类找..发现没 A父类C 类型 所以会向上转型为A 但是B类复写了这方法所以就是结果 B and A
            System.out.println(a2.show(d));   ⑥  //这里是多态B类找..发现继承了A的 D类型 所以呢 就是A and D
            System.out.println(b.show(b));    ⑦ //这里就直接找B类型 结果就是B and B
            System.out.println(b.show(c));    ⑧ //这里找B类型 发现没C 类型 C是继承B的 所以会向上转型为B就是 B and B
            System.out.println(b.show(d));    ⑨   
//这里找B类型 发现继承了A的 D类型 所以呢 就是A and D




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2