首先看一段代碼來考考大家,請大家在不運行程式的情況下,輸出以下代碼的結果:
class Insect {int i = 9;int j;Insect() {prt("i = " + i + ", j = " + j);j = 39;}static int x1 = prt("static Insect.x1 initialized");static int prt(String s) {System.out.println(s);return 47;}}public class Test extends Insect {int k = prt("Beetle.k initialized");Test() {prt("k = " + k);prt("j = " + j);}static int x2 = prt("static Beetle.x2 initialized");static int prt(String s) {System.out.println(s);return 63;}public static void main(String[] args) {prt("Beetle constructor");Test b = new Test();}}
代碼的結果:
static Insect.x1 initializedstatic Beetle.x2 initializedBeetle constructori = 9, j = 0Beetle.k initializedk = 63j = 39
如果你的結果是正確的,那我真是很佩服了……
對Test運行Java 時,發生的第一件事情是裝載程式到外面找到那個類。在裝載過程中,裝載程式注意它
有一個基礎類(即extends 關鍵字要表達的意思),所以隨之將其載入。無論是否準備產生那個基礎類的一
個對象,這個過程都會發生(請試著將對象的建立代碼當作注釋標註出來,自己去證實)。
若基礎類含有另一個基礎類,則另一個基礎類隨即也會載入,以此類推。接下來,會在根基礎類(此時是
Insect)執行 static 初始化,再在下一個衍生類執行,以此類推。保證這個順序是非常關鍵的,因為衍生類
的初始化可能要依賴於對基礎類成員的正確初始化。
此時,必要的類已全部裝載完畢,所以能夠建立對象。首先,這個對象中的所有基礎資料型別 (Elementary Data Type)都會設成它們
的預設值,而將物件控點設為null。隨後會調用基礎類構建器。在這種情況下,調用是自動進行的。但也完
全可以用super 來自行指定構建器調用(就象在Test()構建器中的第一個操作一樣)。基礎類的構建採用
與衍生類構建器完全相同的處理過程。基礎順構建器完成以後,執行個體變數會按本來的順序得以初始化。最
後,執行構建器剩餘的主體部分。