淺談Java對象的初始化順序

當一個類使用new關(guān)鍵字來創(chuàng)建新的對象的時候,比如Person per = new Person();JVM根據(jù)Person()尋找匹配的類,然后找到這個類相匹配的構(gòu)造方法,這里是無參構(gòu)造,如果程序中沒有給出任何構(gòu)造方法,則JVM默認會給出一個無參構(gòu)造。當創(chuàng)建一個對象的時候一定對調(diào)用該類的構(gòu)造方法,構(gòu)造方法就是為了對對象的數(shù)據(jù)進行初始化。JVM會對給這個對象分配內(nèi)存空間,也就是對類的成員變量進行分配內(nèi)存空間,如果類中在定義成員變量就賦值的話,就按初始值進行運算,如果只是聲明沒有賦初始值的話,JVM會按照規(guī)則自動進行初始化賦值。而成員方法是在對象調(diào)用這個方法的時候才會從方法區(qū)中加載到棧內(nèi)存中,用完就立即釋放內(nèi)存空間。

筆者認為學(xué)到類與對象時的一個關(guān)鍵點:初始化順序。

先假設(shè)一個類,如圖中一樣各組成都有,那么他的初始化順序是


1、初始化類變量(即static修飾的成員變量),并未賦值。不管寫的位置在哪里,只要是類變量,系統(tǒng)總會先找到它進行變量初始化。

2、執(zhí)行靜態(tài)代碼塊和類變量定義式,兩者根據(jù)寫的位置來決定先后,先寫先執(zhí)行。其實從某種角度上看,可以把類變量定義賦值視為兩部分:一部分是定義變量,一部分賦值。而這個賦值部分可以看做是一個靜態(tài)代碼塊。兩個靜態(tài)代碼塊的執(zhí)行順序自然是看寫的位置的先后了。

3、初始化實例變量(即未被static修飾的成員變量),并未賦值。同樣的,不管寫的位置在哪里,在創(chuàng)建對象時執(zhí)行到這步時,系統(tǒng)總會找到它進行變量初始化。

4、執(zhí)行構(gòu)造代碼塊和實例變量定義賦值式,兩者同樣根據(jù)寫的位置先后來決定執(zhí)行順序先后,同樣可以按2中所寫來理解。但是,這里要注意的就是構(gòu)造代碼塊是可以調(diào)用靜態(tài)變量的,實例變量定義賦值式可以看做是只對實例變量進行賦值的構(gòu)造代碼塊。

5、執(zhí)行構(gòu)造函數(shù)。構(gòu)造函數(shù)同樣可以調(diào)用靜態(tài)變量和實例變量。

初始化結(jié)束。

這里說明一點:這是初始化順序,不等同于語句程序的執(zhí)行過程(畢老師的視頻里有個很詳細的例子講這個執(zhí)行過程,不知道的一定要去看)。因此在上面的初始化順序里沒有成員函數(shù)(靜態(tài)或者非靜態(tài)都沒有),這是因為成員函數(shù)都是調(diào)用了才執(zhí)行,雖然靜態(tài)函數(shù)已經(jīng)被加載進了方法區(qū),但初始化過程中并沒有執(zhí)行過。

關(guān)于這個初始化順序,其實一句話可以概括:

先初始化類變量然后賦值,再初始化實例變量然后賦值。

由于靜態(tài)代碼塊可以調(diào)用靜態(tài)變量,構(gòu)造代碼塊和構(gòu)造函數(shù)可以調(diào)用實例變量和靜態(tài)變量,這塊很容易來個看似復(fù)雜的代碼,將一個變量變來變?nèi)サ模靼走@個初始化順序就會解決很快了。

接下來,看幾個例子來驗證下:

第一個:

public class JustForTest {

public static void main(String[] args) {

Car c=new Car();

sop("i="+c.i);

}

static void sop(Object obj){

System.out.println(obj);

}

}

class Car{

static int i=1;? //定義賦值

static {? ? ? ? ? //靜態(tài)代碼塊

i=4;

}

}

運行結(jié)果為:i=4.

只改寫Car的內(nèi)部,讓靜態(tài)代碼塊和靜態(tài)變量的定義賦值互換位置,其他保持不變:

class Car{

static {? ? ? ? ? //靜態(tài)代碼塊

i=4;

}

static int i=1;? //定義賦值

}

運行結(jié)果為:i=1.

最后來個綜合點的,把Car再改寫一下:

class Car{

static int i=1;? ? //靜態(tài)變量定義賦值

Car(){? ? ? ? ? ? //構(gòu)造函數(shù)

i=2;

}

static {? ? ? ? ? //靜態(tài)代碼塊

i=4;

}

{? ? ? ? ? //構(gòu)造代碼塊

i=3;

}

}

運行結(jié)果是:i=2.

按初始化順序,構(gòu)造函數(shù)是最后初始化的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容