之前對構造函數的調用順序一直很迷,只知道很死板地記着“父類構造函數先於子類構造函數調用”,但是其中的原因並沒有去深究。前幾周大概看了一遍JAVA編程思想,真的是博大精深…但是對這個概念起碼有了一點自己的看法。歡迎指正哦~
class Fu{
}
class Zi extends Fu{
}
public class Demo1 {
public static void main(String[] args) {
Fu fu = new Fu();
Zi zi = new Zi();
}
}
上面這段代碼是可以運行起來的,雖然它沒有任何實際的用處。但是,我們應該能想到,編譯器爲我們做了一些事情,首先,類是一定會有構造方法的。如果你沒寫,編譯器就會自動創建一個默認構造方法。默認構造方法不帶任何參數,也沒有方法的實體。
修改一下代碼,在子類中寫一個無參構造方法。
class Fu{
}
class Zi extends Fu{
Zi(){
System.out.println("子類的無參構造方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Fu fu = new Fu();
Zi zi = new Zi();
}
}
運行結果:
子類的無參構造方法
這裏應該無需解釋了吧。
那麼,進入正題。爲什麼先執行父類的構造方法呢?
答案就是:super()!!!
繼承的規則就是:子類的構造方法中,第一行代碼應該是super語句。如果沒有顯式地寫出來,就會自動加上一個super()。所以上面的代碼可以理解爲:
class Fu{
/*
* Fu(){}; //編譯器自動生成的默認構造方法
*/
}
class Zi extends Fu{
Zi(){
//super(); //編譯器自動調用無參的父類構造方法
System.out.println("子類的無參構造方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Fu fu = new Fu();
Zi zi = new Zi();
}
}
其實總的來說,執行Zi zi = new Zi()時,還是會先進入子類的構造方法中,只不過由於第一行代碼就是super(),等於先調用父類的無參構造方法。所以就有了“先執行父類構造,在執行子類構造方法”這一說,但我們應該清楚,調用的入口,其實是該類本身,而不是它的父類啥的…
下面這段代碼,我想你應該能很快地找出問題所在:
class Fu{
Fu(int age){
System.out.println("父類的構造方法");
}
}
class Zi extends Fu{
Zi(){
System.out.println("子類的無參構造方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Zi zi = new Zi();
}
}
我們顯式地爲父類寫了一個有參構造方法,此時編譯器不會再爲父類生成無參構造方法。當聲明一個子類對象並且獲得實例時,會調用其構造方法,子類構造方法第一行默認爲super(),也就是調用父類的無參構造方法,但是父類並沒有無參構造方法,所以會報錯。
解決辦法就是:再爲父類重載一個無參構造方法,或者是在子類構造方法的第一行顯式地加上一行代碼:
super(int型參數);
第一篇博客先寫簡單一點的嘻嘻~