當一個類使用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ù)是最后初始化的。