2012-02-21 197 views
3

給定一個隨機類:子類構造函數 - 爲什麼必須爲子類構造函數存在默認構造函數?

public class A<T> { 
    public T t; 

    public A() {} // <-- why is this constructor necessary for B? 
    public A (T t) { 
     this.setT(t); 
    } 
    public T getT() { 
     return this.t; 
    } 
    protected void setT (T t) { 
     this.t = t; 
     return; 
    } 
} 

和擴展類:

public class B extends A<Integer> { 
    public B (Integer i) { 
     this.setT(i); 
    } 
} 

爲什麼B都必須一有空的構造?我會假定它會使用類似的構造函數而不是默認的構造函數。我嘗試編譯沒有默認的構造函數,但我得到沒有它的以下消息...

java.lang.NoSuchMethodError: A: method <init>()V not found at B.<init> 

任何人都可以解釋這是爲什麼?

回答

9

重要的一點是要明白,任何構造函數的第一行是調用超級構造函數。如果你不自己調用一個超級構造函數,編譯器會使你的代碼變得簡短一些,在底部插入super()

此外,如果你沒有任何構造一個空的默認構造函數 - 這裏A()B() - 將自動插入。

你有一個情況下,你不必在你的B-構造一個super(...),所以編譯器插入super()調用本身,但你有A-構造函數參數,以便在默認A() - 構造函數沒有插入,你必須手動提供A() - 構造函數,或者調用A(i)構造函數。在這種情況下,我建議只是有

public class B extends A<Integer> { 
    public B (Integer i) { 
     super(i); 
    } 
} 
+0

這是正確的說,當一個對象被實例化時,它所繼承的所有對象也被實例化(如構建塊)? – Zak 2012-02-21 01:20:04

+0

我寧願說當你實例化一個對象時,構造函數負責初始化對象。如果你繼承它,那麼子類的構造函數負責初始化添加的部分,而超級構造函數負責剩下的部分。這一直遞歸地應用於Object類本身。 – 2012-02-21 01:27:56

6

您可以用您自己的構造在A,但你必須從B的構造函數顯式調用它,如:

public B(Integer i) { 
    super(i); 
    ... 
} 

如果你不這樣做,編譯器會嘗試實例A本身,通過調用它的默認構造函數。

2

如果不撥打電話,使用super(i)爲您的構造函數的第一行超級構造函數就會隱式調用默認的構造函數的超級

相關問題