這篇文章總結了一個關于Java構造函數的常見問題。
1.為什么創建子類的對象也調用父類的構造函數?
class Super {
String s;
public Super(){
System.out.println("Super");
}
}
public class Sub extends Super {
public Sub(){
System.out.println("Sub");
}
public static void main(String[] args){
Sub s = new Sub();
}
}
輸出:
Super
Sub
當從另一個類繼承時,必須在構造函數中首先調用super() 。 如果沒有,則編譯器將插入該調用。 這就是為什么在創建Sub對象時也調用super構造函數的原因。
這不會創建兩個對象,只創建一個子類對象。 有父類構造函數調用的原因是,父類可能有私有字段需要由其構造函數初始化。
編譯器插入父類構造函數后,子類構造函數如下所示:
public Sub(){
super();
System.out.println("Sub");
}
2.常見錯誤消息:隱式父類構造函數對于默認構造函數是未定義的
這是很多Java開發人員看到的編譯錯誤消息:
“隱式父類構造函數對于默認構造函數是未定義的,必須定義一個顯式構造函數”
Implicit-super-constructor-is-undefined-for-default-constructor.png
出現此編譯錯誤是因為默認的父類構造函數未定義。 在Java中,如果一個類沒有定義構造函數,編譯器默認會為該類插入一個默認的無參構造函數。 如果構造函數是在父類中定義的,在這種情況下,Super(String s),編譯器不會插入默認的無參數構造函數。
子類的構造函數(帶參或無參)將調用無父類的無參構造函數。 由于編譯器試圖向子類中的2個構造函數中插入super() ,但父類的默認構造函數未定義,因此編譯器會報告錯誤消息。
要解決這個問題,只需要
- 添加一個Super() 構造函數給Super類
public Super(){
System.out.println("Super");
}
或者2)刪除自定義的父類構造函數,
或者3)將 Super(value) 添加到子構造函數。
3. 在子類構造函數中顯式調用父類構造函數
sub-constructor-with-parameter.png
子類構造函數使用參數顯式調用父類構造函數。 父類構造函數被定義,并且被調用。
4. 規則
簡而言之,規則是:子類構造函數必須由程序員顯式調用或由編譯器隱式地調用。 無論哪種方式,被調用的超級構造函數都必須被定義。