2015-08-15 73 views
-2

爲何輸出是:Java的繼承構造函數是如何工作的?

> B.foo(): bar = null 
> B.foo(): bar = B.bar 
>a.bar = A.bar 
>B.foo(): bar =B.bar 

但不是:

> B.foo(): bar = null 
> A.foo(): bar = A.bar 
>a.bar = A.bar 
>B.foo(): bar =B.bar 

1)B延伸的這樣不就設打電話到A的類? 2)爲什麼通過a.bar調用A而不是B? 3)你能解釋一下輸出嗎? 代碼:

public class A { 
    String bar= "A.bar"; 
    A() { foo(); } 
    public void foo() { 
     System.out.println("A.foo(): bar = "+ bar); 
    } 
} 
public class B extends A { 
    String bar= "B.bar"; 
    B() { foo(); } 
    public void foo() { 
     System.out.println("B.foo(): bar = "+ bar); 
    } 
} 
public class C { 
    public static void main(String[] args) { 
     A a= newB(); 
     System.out.println("a.bar = "+ a.bar); 
     a.foo(); 
    } 
} 
+0

請修復您的代碼。它不會按原樣編譯。 – Carcigenicate

+0

爲什麼按行:「A a = new B();」輸出有兩行? – user

+0

方法可以重寫,字段不能。 [這個問題可能有助於解釋](http://stackoverflow.com/questions/9414990/if-you-override-a-field-in-a-subclass-of-a-class-the-subclass-has-two- fields-wi)爲什麼具有相同名稱的兩個字段不被視爲具有相同簽名的兩個方法相同。 – Obicere

回答

2

當實例有繼承一個類,父類的構造函數首先被調用。

所以在這種情況下,首先調用A的構造函數。第二個調用B的構造函數。

B.foo(): bar = null // output from B.foo() invoked from A's constructor 
B.foo(): bar = B.bar // output from B.foo() invoked from B's constructor 

在這兩種情況下,構造函數調用foo()。無論是FOO()這兩類定義,因爲foo()事實的調用是多態性,正在創建的實例B型的,在構造函數調用,這是Bfoo()方法被稱爲。這就是爲什麼兩條輸出線都以B.foo(): bar = ...開頭的原因。

最後,之所以第一行打印= null而不是B.bar是因爲它試圖之前的B類,甚至還開始初始化其字段來打印B類中的bar變量的值,所以價值仍然是nullBbar變量只被初始化A的構造函數已完成其工作。

這就是爲什麼你永遠不想調用類構造函數中的overrideable方法的原因。它會導致這樣的意外行爲,您可能無意中讀取未初始化的字段。 This thread更詳細地解釋了這一點。

+0

非常感謝! – user