資源描述:
《【深入java虛擬機(jī)(3)】:類初始化-編程開發(fā)技術(shù)》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在工程資料-天天文庫。
1、【深入Java虛擬機(jī)(3)]:類初始化-編程開發(fā)技術(shù)【深入Java虛擬機(jī)(3)】:類初始化原文出處:蘭亭風(fēng)雨類初始化是類加載過程的最后一個(gè)階段,到初始化階段,才真正開始執(zhí)行類中的Java程序代碼。虛擬機(jī)規(guī)范嚴(yán)格規(guī)定了有且只有四種情況必須立即對類進(jìn)行初始化:?遇到new、getstatic>putstatic>invokestatic這四條7節(jié)碼指令時(shí),如果類還沒冇進(jìn)行過初始化,則需要先觸發(fā)其初始化。生成這四條指令最常見的Java代碼場景是:使用new關(guān)鍵字實(shí)例化對象吋、讀取或設(shè)置一?個(gè)類的靜態(tài)字段(static)吋(被static修飾乂被final修飾的,己在編譯期把結(jié)果放入常量
2、池的靜態(tài)字段除外)、以及調(diào)用一個(gè)類的靜態(tài)方法時(shí)。?使用Javadang.refect包的方法對類進(jìn)行反射調(diào)用時(shí),如果類還沒冇進(jìn)行過初始化,則需要先觸發(fā)其初始化。?當(dāng)初始化一個(gè)類的時(shí)候,如果發(fā)現(xiàn)其父類還沒有進(jìn)行初始化,則需要先觸發(fā)其父類的初始化。?當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶需要指定一個(gè)要執(zhí)行的主類,虛擬機(jī)會(huì)先執(zhí)行該主類。虛擬機(jī)規(guī)定只有這四種情況才會(huì)觸發(fā)類的初始化,稱為對一個(gè)類進(jìn)行主動(dòng)引用,除此之外所有引用類的方式都不會(huì)觸發(fā)其初始化,稱為被動(dòng)引用。下面舉一些例子來說明被動(dòng)引用。1、通過了類引用父類中的靜態(tài)字段,這時(shí)對了類的引用為被動(dòng)引用,因此不會(huì)初始化子類,只會(huì)初始化父類classFath
3、er{publicstaticintm=33;static{System,out.printin(,z父類被初始化〃);}}classChildextendsFather{static{System,out.printin(z,子類被初始化〃);}}publicclassStaticTcst{publicstaticvoidmain(String[]args){System.out.println(Child.m);執(zhí)行后輸岀的結(jié)果如下:父類被初始化33對于靜態(tài)字段,只有直接定義這個(gè)字段的類才會(huì)被初始化,因此,通過其子類來引用父類中定義的靜態(tài)字段,只會(huì)觸發(fā)父類的初始化而不會(huì)觸發(fā)子
4、類的初始化。2、常量在編譯階段會(huì)存入調(diào)用它的類的常量池中,木質(zhì)上沒有一直接引用到定義該常量的類,因此不會(huì)觸發(fā)定義常量的類的初始化classConst{publicstaticfinalStringNAME=〃我是常量〃;static{System,out.printin(〃初始化Const類〃);}}publicclassFinalTest{publicstaticvoidmain(String[]args){System,out.printin(Const.NAME);}}執(zhí)行后輸出的結(jié)果如下:我是常量雖然程序屮引用了const類的常量NAME,但是在編譯階段將此常量的值“我是
5、常量”存儲(chǔ)到了調(diào)用它的類FinalTest的常量池中,對常量Const.NAME的引用實(shí)際上轉(zhuǎn)化為了FinalTest類對口身常量池的引用。也就是說,實(shí)際上FinalTest的Class文件Z屮并沒冇Const類的符號引用入口,這兩個(gè)類在編譯成Class文件后就不存在任何聯(lián)系了。3、通過數(shù)組定義來引用類,不會(huì)觸發(fā)類的初始化classConst{static{System,out.printin(,z初始化Const類〃);publicclassArrayTest{publicstaticvoidmain(String[]args){Const[]con二newConst[5];執(zhí)
6、行后不輸岀任何信息,說明Const類并沒有被初始化。但這段代碼里觸發(fā)了另一個(gè)名為“LLConst”的類的初始化,它是一個(gè)由虛擬機(jī)自動(dòng)生成的、直接繼承于java.lang.Object的子類,創(chuàng)建動(dòng)作由字節(jié)碼指令newarray觸發(fā),很明顯,這是一個(gè)對數(shù)組引用類型的初初始化,而該數(shù)組中的元素僅僅包含一個(gè)對Const類的引用,并沒有對其進(jìn)行初始化。如果我們加入對con數(shù)組屮各個(gè)Const類元素的實(shí)例化代碼,便會(huì)觸發(fā)Const類的初始化,如下:classConst{static{System,out.printl初始化Const類〃);publicclassArrayTest{publ
7、icstaticvoidmain(String[]args){Const[]con二newConst[5];for(Consta:con)a=newConst();}}這樣便會(huì)得到如下輸出結(jié)果:初始化Const類根據(jù)四條規(guī)則的第一條,這里的new觸發(fā)了Const類。最后看一下接口的初始化過程與類初始化過程的不同。接口也有初始化過程,上面的代碼中我們都是用靜態(tài)語句塊來輸岀初始化信息的,而在接口中不能使用“stdtic{}”語句塊,但編譯器仍然會(huì)為接口生成類構(gòu)造器,用