我們在定義一個類的時候,如果需要重新寫一個構造函數,就必須要寫一個無參構造函數,如下代碼所示,那這到底是為什么?
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修飾的。這就很令人費解了,查了一下,應該是基於以下原因:
