? ? 今天在課上復(fù)習(xí)了Java的初始化順序放闺,一直有點(diǎn)疑惑凶赁,搞不明白,所以打算寫下來臊恋,記錄一下衣洁。
? 先說一下Java程序初始化的順序:父類靜態(tài)變量>父類靜態(tài)代碼塊>子類靜態(tài)變量>子類靜態(tài)代碼塊>父類非靜態(tài)變量>父類非靜態(tài)代碼塊>父類構(gòu)造器>子類非靜態(tài)變量>子類非靜態(tài)代碼塊>子類構(gòu)造器。
Java程序初始化一般遵循3個(gè)原則
1.靜態(tài)對(duì)象(變量)先于非靜態(tài)對(duì)象(變量)初始化抖仅。其中靜態(tài)對(duì)象(變量)只初始化一次坊夫,因?yàn)閟tatic在jvm中只有一塊區(qū)域存儲(chǔ),方法區(qū)(Method Area)撤卢,他之所以被稱為靜態(tài)是因?yàn)閺某绦騽?chuàng)建到死亡他的地址值都不會(huì)改變环凿,他只在class類對(duì)象初次加載時(shí)初始化,因此static只需要初始化一次放吩,而非靜態(tài)對(duì)象(變量)可能會(huì)初始化很多次智听。
2.如果類之間存在繼承關(guān)系,那么父類優(yōu)先于子類進(jìn)行初始化渡紫。
3.按照成員變量的定義順序進(jìn)行初始化到推。即使變量定義散布于方法之中,他們依然在任何方法(包括構(gòu)造函數(shù))被調(diào)用前先初始化腻惠。
接下來我們先來看來《Thinking in Java 》的代碼示例:
在Card中环肘,Tag對(duì)象的實(shí)例化故意到處散布欲虚,in order to 使得他們都在構(gòu)造器進(jìn)入或者發(fā)生其它任何事情之前得到初始化集灌。除此之外,t3在構(gòu)造器內(nèi)部得到了重新的初始化复哆。
下面我們來看看運(yùn)行結(jié)果:
如果想在定義的同時(shí)進(jìn)行初始化欣喧,采取的方法與非靜態(tài)值表面看起來是相同的。但由于static值只有一個(gè)存儲(chǔ)區(qū)域梯找,所以無論創(chuàng)建了多少個(gè)對(duì)象唆阿,都必然會(huì)遇到何時(shí)對(duì)那個(gè)存儲(chǔ)區(qū)域進(jìn)行初始化的問題。下面來看一段《Thinking in Java 》代碼:
大家拿出紙筆來算算會(huì)輸出個(gè)什么個(gè)結(jié)果嗎驯鳖,你的思路是否還清晰呢,還是像筆者一樣已經(jīng)云里霧里了久免,好了不賣關(guān)子了浅辙,我們來看看輸出的結(jié)果:
是否和你在紙上的答案一樣呢?
我們來剖析一下這個(gè)程序阎姥,首先看main方法记舆,main方法里首先會(huì)初始化靜態(tài)對(duì)象t2,t3,在jvm的方法區(qū)里創(chuàng)建一個(gè)t2的靜態(tài)對(duì)象呼巴,指向Table類泽腮,然后在創(chuàng)建一個(gè)t3的靜態(tài)對(duì)象指向Cupboard.
然后程序繼續(xù)運(yùn)行到Table類里御蒲,初始化靜態(tài)對(duì)象b1,跳轉(zhuǎn)到Bowl類诊赊,執(zhí)行Bowl的構(gòu)造器厚满,打印輸出Bowl(1),進(jìn)入bowl類碧磅,初始化靜態(tài)對(duì)象b2痰滋,跳轉(zhuǎn)到Bowl類,執(zhí)行Bowl的構(gòu)造器续崖,打印輸出Bowl(2)敲街,回到Table類,執(zhí)行Table類的構(gòu)造器严望,打印輸出Table()多艇,執(zhí)行b2.f(1),打印輸出f(1)像吻,此時(shí)峻黍,靜態(tài)對(duì)象t2的任務(wù)已經(jīng)完成了。
接下來時(shí)t3的任務(wù)拨匆,進(jìn)入Cupboard類姆涩,初始化靜態(tài)對(duì)象b4,跳轉(zhuǎn)到Bowl類惭每,打印輸出Bowl(4)骨饿,初始化靜態(tài)對(duì)象b5,跳轉(zhuǎn)到Bowl類台腥,打印輸出Bowl(5),初始化非靜態(tài)對(duì)象b3宏赘,跳轉(zhuǎn)到Bowl類,打印輸出Bowl(3),然后執(zhí)行Cupboard的構(gòu)造器黎侈,打印輸出Cupboard()察署,next,執(zhí)行b4.f(2)峻汉,打印輸出f(2)贴汪,此時(shí)靜態(tài)對(duì)象t3的任務(wù)已經(jīng)完成了。
回到main函數(shù)里休吠,執(zhí)行非靜態(tài)變量扳埂,打印輸出一個(gè)Creating new Cupboard() in main,在new一個(gè)Cupboard蛛碌,初始化非靜態(tài)對(duì)象b3聂喇,跳轉(zhuǎn)到Bowl類,打印輸出Bowl(3),然后執(zhí)行Cupboard的構(gòu)造器,打印輸出Cupboard()希太,next克饶,執(zhí)行b4.f(2),打印輸出f(2)誊辉,然后繼續(xù)打印一個(gè)Creating new Cupboard() in main矾湃,繼續(xù)new一個(gè)Cupboard,初始化非靜態(tài)對(duì)象b3堕澄,跳轉(zhuǎn)到Bowl類邀跃,打印輸出Bowl(3),然后執(zhí)行Cupboard的構(gòu)造器,打印輸出Cupboard()蛙紫,next拍屑,執(zhí)行b4.f(2),打印輸出f(2)坑傅。
最后執(zhí)行t2.f2(1)僵驰,t2指向的是Table類,所以打印輸出f2(1)唁毒,同理蒜茴,t3.f3(3)打印輸出f3(3).
到此為止,這段代碼已經(jīng)被我們解剖的清清楚楚了浆西,所以對(duì)Java的初始化順序應(yīng)該印象更深了吧粉私!