如果類別有繼承關係,在建構子類別實例後,會先進行父類別定義的初始流程,再進行子類別中定義的初始流程,也就是建構子類別實例後,會先執行父類別建構式定義的流程,再執行子類別建構式定義的流程。
建構式可以重載,父類別中可重載多個建構式,如果子類別建構式中沒有指定執行父類別中哪個建構式,預設會呼叫父類別中無參數建構式。如果你如下撰寫程式:
class Some {
Some() {
System.out.println("呼叫Some()");
}
}
class Other extends Some {
Other() {
System.out.println("呼叫Other()");
}
}
如果嘗試new Other()
,看來好像是先執行Some()
中的流程,再執行Other()
中的流程,也就是先顯示"呼叫Some()",再顯示"呼叫Other()"。很奇怪是吧!先繼續往下看,就知道為什麼了。如果想執行父類別中某建構式,可以使用super()
指定。例如:
class Some {
Some() {
System.out.println("呼叫Some()");
}
Some(int i) {
System.out.println("呼叫Some(int i)");
}
}
class Other extends Some {
Other() {
super(10);
System.out.println("呼叫Other()");
}
}
在這個例子中,new Other()
時,先呼叫了Other()
版本的建構式,super(10)
表示呼叫父類別建構式時傳入int
數值10,因此就是呼叫了父類別中Some(int i)
版本的建構式,而後再繼續Other()
中super(10)
之後的流程。其實當你這麼撰寫時:
class Some {
Some() {
System.out.println("呼叫Some()");
}
}
class Other extends Some {
Other() {
System.out.println("呼叫Other()");
}
}
先前談過,如果子類別建構式中沒有指定執行父類別中哪個建構式,預設會呼叫父類別中無參數建構式,也就是等於你這麼撰寫:
class Some {
Some() {
System.out.println("呼叫Some()");
}
}
class Other extends Some {
Other() {
super();
System.out.println("呼叫Other()");
}
}
所以執行new Other()
時,是先執行Other()
中的流程,而Other()
中指定呼叫父類別無參數建構式,而後再執行super()
之後的流程。
注意!this()
與super()
只能擇一呼叫,而且一定要在建構式第一行執行。
那麼你知道以下為什麼會編譯錯誤嗎?
編譯器會在你沒有撰寫任何建構式時,自動加入沒有參數的預設建構式(Default constructor),如果自行定義了建構式,就不會自動加入任何建構式了。在上圖中,
Some
定義了有參數的建構式,所以編譯器不會再加入預設建構式,Other
的建構式中沒有指定呼叫父類別中哪個建構式,那就是預設呼叫父類別中無參數建構式,但父類別中現在哪來的無參數建構式呢?因此編譯失敗了!有些場合建議,如果定義了有參數的建構式,也可以加入無參數建構式,即使內容為空也無所謂,這是為了日後使用上的彈性,例如運用反射(Reflection)機制生成物件的需求,或者是繼承時呼叫父類別建構式時的方便。