zoukankan      html  css  js  c++  java
  • java 类继承估计99%的人都不知道的问题?

    转: https://www.zhihu.com/question/41924954

    下面代码的输出是什么?

    实际结果是:
    I am in B, value is 0
    I am in B, value is 44
    22
    对这一结果我没有任何思路,不知道为什么,尤其是0.

    public class Test {
        public static void main(String[] args) {
            P b = new B();
            System.out.println(b.a);
        }
    
        static class P {
            public int a = 11;
    
            public P() {
                a = 22;
                diplay();
            }
    
            public void diplay() {
                System.out.println("I am in P, value is " + a);
            }
        }
    
        static class B extends P {
            int a = 33;
    
            public B() {
                a = 44;
                diplay();
            }
    
            public void diplay() {
                System.out.println("I am in B, value is " + a);
            }
        }
    }

    解释1:

    例子里,P.display()与B.display()构成覆写(override)关系:后者覆写前者。这是虚方法的多态性的表现。
    所以在创建B类实例时,虽然会(显式或隐式)调用到P的构造器,但在P的构造器里调用的display()方法永远是按照虚方法的查找规则,找到该实例最准确的实现,所以P()里调用display()找到的是B.display()方法。

    而字段永远不参与多态,哪个类的方法访问某个名字的字段时,该名字指的就是该类能看到的那个字段。当子类声明了与父类同名的字段时,虽然在子类里两个字段都会存在,但是子类的字段会遮蔽了父类的同名字段。
    此例中,P.display()里访问“a”访问的是P.a,而B.display()里访问“a”访问的是B.a。

    由于题主给的例子里两次display()调用都调用到了B.display(),显示的值自然就是B.a的值。一切就都解决了。 
     
    解释2:
    首先,你的這個程序「翻譯」過來,是這樣的:(每個 a 的賦值實際都是在 constructor 裏執行的)
    public class Test {
    
       public static void main( String [] args ) {
    
          P b = new B(); //                                              01
          System.out.println( b.a ); //                                  15
       }
    
       static class P {
    
          public int a;
    
          public P() { //                                                04
             a = 11; //                                                  05
             a = 22; //                                                  06
             diplay(); //                                                07
          }
    
          public void diplay() {
             System.out.println( "I am in P, value is " + a );
          }
       }
    
       static class B extends P {
    
          int a;
    
          public B() { //                                                02
             super(); //                                                 03
             a = 33; //                                                  10
             a = 44; //                                                  11
             diplay(); //                                                12
          }
    
          public void diplay() { //                                      08, 13
             System.out.println( "I am in B, value is " + a ); //        09, 14
          }
       }
    }
    註釋裏的數字,是每一行發生的順序。
    可以看到當09發生的時候,輸出的是 B 自己的 a,而這個 a 是一個成員變量,同時沒有被賦任何值,所以是 int 成員變量的 default value,即0。
  • 相关阅读:
    BZOJ 1899: [Zjoi2004]Lunch 午餐
    BZOJ3670: [Noi2014]动物园
    BZOJ3712: [PA2014]Fiolki
    BZOJ1057: [ZJOI2007]棋盘制作
    BZOJ4326: NOIP2015 运输计划
    BZOJ4721: [Noip2016]蚯蚓
    BZOJ1131: [POI2008]Sta
    BZOJ1856: [Scoi2010]字符串
    BZOJ4003: [JLOI2015]城池攻占
    [AH2017/HNOI2017]单旋
  • 原文地址:https://www.cnblogs.com/swing07/p/14513179.html
Copyright © 2011-2022 走看看