java對(duì)象創(chuàng)建過(guò)程(zhuan)
凡是用過(guò)面向?qū)ο笳Z(yǔ)言的人都寫過(guò)構(gòu)造函數(shù)(廢話一句),java程序員更是如此。由于java是純面向?qū)ο蟮恼Z(yǔ)言,所以可能造成構(gòu)造函數(shù)滿天飛的情況....但是,你知道,當(dāng)執(zhí)行構(gòu)造函數(shù)的時(shí)候,這短短的一句在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();
}
}
奇怪吧,下面解釋一下調(diào)用new B()時(shí)到底發(fā)生了什么
奇怪吧,下面解釋一下調(diào)用new B()時(shí)到底發(fā)生了什么- 當(dāng)然是調(diào)用B的構(gòu)造函數(shù)了
- 由于B是從A繼承而來(lái),會(huì)默認(rèn)的調(diào)用A的無(wú)參構(gòu)造函數(shù)。這里注意,如果A沒有提供默認(rèn)構(gòu)造函數(shù),而是提供了有參的構(gòu)造函數(shù),編譯將會(huì)出錯(cuò)
- 初始化A中的實(shí)例變量。由于varA沒有在聲明時(shí)賦值,JVM會(huì)將它初始化為0。此時(shí),還沒有執(zhí)行A構(gòu)造函數(shù)中的代碼。
- 執(zhí)行System.out.println("inside A"),輸出第一行。然后調(diào)用getVar()。這里可以花時(shí)間解釋一下為什么輸出的是varB而不是varA。getVar()是覆蓋方法。在java中,覆蓋方法是動(dòng)態(tài)決定的,也就是根據(jù)擁有它的對(duì)象類型來(lái)執(zhí)行,而不是根據(jù)引用類型來(lái)決定。這一點(diǎn)正好和重載方法相反。因此,這里會(huì)執(zhí)行聯(lián)編后B的getVar(),而此時(shí)varB還沒有初始化,所以默認(rèn)為0
- 執(zhí)行到這里,A類構(gòu)造函數(shù)的內(nèi)容已經(jīng)完畢,返回B的構(gòu)造函數(shù),執(zhí)行System.out.println("inside B")
- 此時(shí)繼續(xù)執(zhí)行g(shù)etVar(),這時(shí)也是執(zhí)行B的方法,由于varB在聲明時(shí)已經(jīng)顯示初始化,故輸出varB = 123
- 執(zhí)行System.out.println("varA = " + varA)。從前面可以看出,A類的getVar()根本沒有執(zhí)行,所以varA一直沒有被賦值,所以它的值還是0
沒想到吧,一句短短的new B()可以引起這么多的調(diào)用。其實(shí),如果涉及到靜態(tài)域或變量,情況要比上面復(fù)雜的多,有興趣的朋友可以試驗(yàn)一下
總結(jié)一下,關(guān)于調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)類的過(guò)程如下
- 調(diào)用構(gòu)造函數(shù)
- 初始化該類的靜態(tài)變量
- 初始化該類的靜態(tài)塊(static block)
- 調(diào)用該類構(gòu)造函數(shù)的第一句(super或this)。如果沒有寫出,默認(rèn)調(diào)用super()
- 初始化變量/執(zhí)行語(yǔ)句塊
- 執(zhí)行構(gòu)造函數(shù)剩下的內(nèi)容
posted on 2006-03-03 20:40 都市淘沙者 閱讀(468) 評(píng)論(0) 編輯 收藏 所屬分類: Java Basic/Lucene/開源資料