這篇文章總結了Java使用建構函式中最常遇到的五個問題!
1 為什麼呼叫子類的構造方法的時候,預設會呼叫父類的構造方法
看下面這個簡單的例子:
package cc;
public class Sub extends Super {
public Sub() {
System.out.println("Sub");
}
public static void main(String[] args) {
Sub sub = new Sub();
}
}
class Super {
public Super() {
System.out.println("Super");
}
}
複製程式碼
當繼承自一個類的時候,構造方法就會首先呼叫super()方法。如果沒有顯式的寫這個語句,那麼編譯器就會自動插入這個語句。這就是為什麼我們上面的那個例子程式會先呼叫super的構造方法。 但要切記,** 雖然呼叫了父類的構造方法,但只建立了一個物件也就是子物件。** 之所以要呼叫父類的構造方法,是因為super類可能需要建構函式來初始化一些私有的成員變數。 編譯器自動插入super構造方法後,子類的建構函式就會像下面這樣:
public Sub(){
super();
System.out.println("Sub");
}
複製程式碼
2 常見錯誤:Implicit super constructor is undefined for default constructor. Must define an explicit constructor
Implicit super constructor is undefined for default constructor. Must define an explicit constructor
這個錯誤是很多開發者經常遇到的錯誤,錯誤原因就是找不到超類中的預設建構函式。
看下面的程式碼:
package cc;
public class Sub extends Super {
public Sub(String s) {
}
public static void main(String[] args) {
Sub sub = new Sub();
}
}
class Super {
String s;
public Super(String s) {
this.s = s;
}
}
複製程式碼
上面這段程式碼會報錯: Implicit super constructor Super() is undefined. Must explicitly invoke another constructor。
編譯器錯誤是因為預設的super()無參的建構函式是沒有定義的。在Java中,如果一個類沒有定義建構函式,編譯器會自動插入一個預設的無參的建構函式。 但是,如果類中定義了一個建構函式,編譯器就不會自動插入無參的建構函式了,所以如果我們不顯示定義一個無參的建構函式,那麼這個建構函式就不存在。
上一小節,我們知道,如果子類的建構函式中,沒有顯示的呼叫父類的建構函式,那麼,編譯器就會插入super(),也就是自動呼叫無參的建構函式。但是此時,父類沒有無參的建構函式,所以就會報錯了。
解決這個問題很簡單,我們可以給父類插入一個無參的建構函式,或者在子類建構函式中顯示的呼叫的父類有參建構函式。
在子類的建構函式中顯示的呼叫父類的建構函式
下面的程式碼是正確的。
建構函式的使用規則
簡單的說,在使用的時候,子類的建構函式必須呼叫父類的建構函式,不管有沒有顯示的宣告。所以,被呼叫的父類建構函式,一定在定義好!
為什麼Java在一個類已經實現了一個帶參的建構函式的時候,不實現預設的無參建構函式?
這是個很有趣的問題。我們知道如果在一個類中沒有宣告一個建構函式,那麼編譯器會隱式的幫我們實現一個無參的建構函式,但如果我們一旦一個建構函式,不管帶不帶引數,那麼編譯器都不會提供預設的建構函式,所以這麼做的原因是為什麼呢?
有一個原因就是,如果我們給所有的類都自動實現一個無參的建構函式,就可能出現問題,會打破類的設計原則。 比如說,考慮這個Scanner類,他有幾個建構函式,你可以通過這幾個建構函式,宣告你想要讀取資料的來源,如果編譯器增加了無參的建構函式,那麼你不給定讀取的資料來源,就會報錯,程式無法執行,因為我們不能不指定一個資料來源就讓他去讀取資料。