我們在定義一個類的時候,如果需要重新寫一個構造函數,就必須要寫一個無參構造函數,如下代碼所示,那這到底是為什么?
public class Fruit { private String name; // 必須顯式聲明一個無參構造函數 public Fruit(){} public Fruit(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
要回答這個問題,我們就來把這個無參構造函數去掉試試。
按照如下方式,用起來也沒多大的問題:
public static void main(String[] args){ Fruit apple = new Fruit("apple"); // print "apple" System.out.println(apple.getName()); }
但是,當我們需要派生一個子類的時候,編譯就報錯了:
public class Apple extends Fruit { // There is no default constructor available in 'cn.zx.demo.Fruit' }
這是因為,子類在使用自己的默認無參構造函數初始化的時候,會執行super()來調用父類的默認無參構造函數,但是父類中此時沒有這樣的構造函數,因此編譯器認為出現了異常。
如果我們在父類Fruit中顯式地聲明一個無參構造函數,就像本文一開始演示的代碼一樣,那么就不會出現這樣的問題了。
再進一步思考,如果子類實例化的時候不使用super()來調用父類的無參構造函數是不是就不會出現這樣的問題了呢?
答案是肯定的:
public class Apple extends Fruit { public Apple(String name){ super(name); } }
只要在子類中指定調用父類中存在的構造函數,那么子類就是可以被正確初始化的,程序編譯也就沒有問題。
然而,我們其實並不能確定將要如何初始化一個子類,而且,我們也不可能為每一個子類都顯式地調用其存在的父類構造函數,這樣太過繁瑣。
比如,我們需要創建一個沒有name屬性的banana對象,那么此時將沒有合適的父類的構造方法供調用:
public class Banana extends Fruit { public Banana (){ // 沒有合適的父類構造函數供調用 } }
所以,為了可擴展,在類中重新寫構造函數的時候,額外聲明一個無參構造函數是一個良好的編程習慣。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以上都是轉載,內容也很好理解,但是今天看業務代碼,無參構造函數是私有的,private修飾的。這就很令人費解了,查了一下,應該是基於以下原因: