java對象創建過程(zhuan)
凡是用過面向對象語言的人都寫過構造函數(廢話一句),java程序員更是如此。由于java是純面向對象的語言,所以可能造成構造函數滿天飛的情況....但是,你知道,當執行構造函數的時候,這短短的一句在JVM中都做了什么嗎?
看下面一段代碼
class A{
public int varA;
public A(){
System.out.println("inside A");
getVar();
}
public void getVar(){
varA = 321;
System.out.println("varA = " + varA);
}
}
public class B extends A{
public int varB = 123;
public B(){
System.out.println("inside B");
getVar();
System.out.println("varA = " + varA);
}
public void getVar(){
System.out.println("varB = " + varB);
}
public static void main(String[] args){
new B();
}
}
奇怪吧,下面解釋一下調用new B()時到底發生了什么
奇怪吧,下面解釋一下調用new B()時到底發生了什么- 當然是調用B的構造函數了
- 由于B是從A繼承而來,會默認的調用A的無參構造函數。這里注意,如果A沒有提供默認構造函數,而是提供了有參的構造函數,編譯將會出錯
- 初始化A中的實例變量。由于varA沒有在聲明時賦值,JVM會將它初始化為0。此時,還沒有執行A構造函數中的代碼。
- 執行System.out.println("inside A"),輸出第一行。然后調用getVar()。這里可以花時間解釋一下為什么輸出的是varB而不是varA。getVar()是覆蓋方法。在java中,覆蓋方法是動態決定的,也就是根據擁有它的對象類型來執行,而不是根據引用類型來決定。這一點正好和重載方法相反。因此,這里會執行聯編后B的getVar(),而此時varB還沒有初始化,所以默認為0
- 執行到這里,A類構造函數的內容已經完畢,返回B的構造函數,執行System.out.println("inside B")
- 此時繼續執行getVar(),這時也是執行B的方法,由于varB在聲明時已經顯示初始化,故輸出varB = 123
- 執行System.out.println("varA = " + varA)。從前面可以看出,A類的getVar()根本沒有執行,所以varA一直沒有被賦值,所以它的值還是0
沒想到吧,一句短短的new B()可以引起這么多的調用。其實,如果涉及到靜態域或變量,情況要比上面復雜的多,有興趣的朋友可以試驗一下
總結一下,關于調用構造函數創建一個類的過程如下
- 調用構造函數
- 初始化該類的靜態變量
- 初始化該類的靜態塊(static block)
- 調用該類構造函數的第一句(super或this)。如果沒有寫出,默認調用super()
- 初始化變量/執行語句塊
- 執行構造函數剩下的內容
posted on 2006-03-03 20:40 都市淘沙者 閱讀(468) 評論(0) 編輯 收藏 所屬分類: Java Basic/Lucene/開源資料