Java類初始化順序詳解
Java 類初始化介紹
java語言在使用過程中最先開始就是初始化,在工作中如果遇到什么問題需 要定位往往到最后也可能是初始化的問題,因此掌握初始化的順序很重要。
根據(jù)java 語言特性,本人針對(duì)初始化中常遇到的一些關(guān)鍵點(diǎn)做了總結(jié),當(dāng)然是基于代碼之上的,主要針對(duì)JVM加載一個(gè)類之后,類的屬性等在內(nèi)存中的初始化,主要靜態(tài)的變量和非靜態(tài)的變量,以及靜態(tài)代碼塊,普通代碼塊等。具體參考下面的圖:

簡單介紹下圖的意思,java類對(duì)象初始化主要包括:
- 靜態(tài)基本變量;
- 靜態(tài)類變量;
- 靜態(tài)代碼塊;
- 普通基本變量;
- 普通類類型變量;
- 普通代碼塊;
- 構(gòu)造方法;
初始化的時(shí)候主要就是這些屬性,但是該類繼承自父類,則初始化順序號(hào)包括基類的這些屬性,即初始化屬性包括本類的這些屬性+父類的這些屬性,并且基類的屬性和本類的屬性交叉初始化。
無繼承關(guān)系初始化
首先查看基本代碼
首先看TestB.java類
private static String tag = "TestB";
//靜態(tài)變量
private static int staticVarA = initVar("staticVarA");
//靜態(tài)代碼塊
static{
initVar("static init block ");
}
//普通變量
private int normalA = initVar("normalA");
// 普通代碼塊
{
initVar("normal init block");
}
public TestB(){
System.out.println(initVar("constructor"));
}
static int initVar(String str){
System.out.println(tag +" "+str);
return 2018;
}其次是 JavaInitWithMain.java 類
private static String tag = "JavaInitWithMain";
//靜態(tài)變量
private static int staticVarA = initVar("staticVarA");
//靜態(tài)代碼塊
static{
initVar("static init block ");
}
//普通變量
private int normalA = initVar("normalA");
// 普通代碼塊
{
initVar("normal init block");
}
private static TestB nB = new TestB();
private TestB nb2 = new TestB();
public JavaInitWithMain(){
System.out.println(initVar("constructor"));
}
static int initVar(String str){
System.out.println(tag +" "+str);
return 2020;
}
public static void main(String[] args) {
System.out.println("-------main method-------");
System.out.println("do nothing");
}接下來是運(yùn)行結(jié)果:

結(jié)果分析:
代碼很簡單,分別在2個(gè)類中的基本屬性,在JavaInitWithMain 類中的main方法中不做任何操作,查看結(jié)果。
根據(jù)結(jié)果可知,JVM加載了JavaInitWithMain類之后初始化了該類的屬性,順序是 靜態(tài)的—>非靜態(tài)的—->構(gòu)造方法,靜態(tài)的包括靜態(tài)的基本變量,靜態(tài)的類類型變量,靜態(tài)代碼塊,這三個(gè)的順序是 程序員的書寫順序。
得出結(jié)論:無繼承關(guān)系時(shí)的初始化順序 靜態(tài)屬性(靜態(tài)基本變量,靜態(tài)類類型變量,靜態(tài)代碼塊)—>非靜態(tài)的屬性(基本類型變量,基本類類型變量,基本代碼塊)—>構(gòu)造方法
存在繼承關(guān)系的初始化
類基本不變,增加TestB的子類TheSonofTestB,如下
public class TheSonofTestB extends TestB {
private static String tag = "TheSonofTestB";
//靜態(tài)變量
private static int staticVarA = initVar("staticVarA");
//靜態(tài)代碼塊
static{
initVar("static init block ");
}
//普通變量
private int normalA = initVar("normalA");
// 普通代碼塊
{
initVar("normal init block");
}
public TheSonofTestB(){
System.out.println(initVar("constructor"));
}
static int initVar(String str){
System.out.println(tag +" "+str);
return 2019;
}
}JavaInitWithMain中增加靜態(tài)的屬性,同時(shí)為了方便查看去掉了改類中的靜態(tài)類變量和靜態(tài)類類型變量,如下: private static TheSonofTestB sonNB = new TheSonofTestB();
查看 輸出結(jié)果,如下:
同樣分析下結(jié)果: 初始化sonNB 時(shí)先去初始化其基類的靜態(tài)屬性,然后初始化TheSonofTestB的靜態(tài)屬性,接下來是父類的基本變量,父類的構(gòu)造,子類的基本變量,最后子類自己的構(gòu)造。
得出結(jié)論: 不管是本類存在繼承還是本類的類對(duì)象屬性存在繼承
在初始化時(shí)都是: 父類的靜態(tài)屬性—->子類的靜態(tài)屬性—->父類的基本類型屬性—->父類的構(gòu)造—>子類的基本屬性—->子類的構(gòu)造

寫在最后
最后我想說2點(diǎn):
1:不管存在不存在繼承,靜態(tài)的屬性—>非靜態(tài)的屬性—->構(gòu)造方法 都是初始化的順序,存在繼承時(shí),依然一樣,只不過父類和子類的這些屬性交替進(jìn)行
2:思考問題: 子類如果覆蓋了父類的靜態(tài)屬性,那么調(diào)用子類的靜態(tài)屬性時(shí),靜態(tài)屬性的值應(yīng)該是什么?子類是靜態(tài)屬性共有幾個(gè)?各位可自行試驗(yàn)
到此這篇關(guān)于Java類初始化順序詳解的文章就介紹到這了,更多相關(guān)Java類初始化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java硬幣翻轉(zhuǎn)倍數(shù)遞增試算實(shí)例
這篇文章主要介紹了Java硬幣翻轉(zhuǎn)倍數(shù)遞增試算實(shí)例,有需要的朋友可以參考一下2013-12-12
springBoot詳細(xì)講解使用mybaties案例
MyBatis本是apache的一個(gè)開源項(xiàng)目iBatis,2010年這個(gè)項(xiàng)目由apache software foundation遷移到了google code,并且改名為MyBatis。2013年11月遷移到Github。iBATIS一詞來源于“internet”和“abatis”的組合,是一個(gè)基于Java的持久層框架2022-05-05
Java異步編程的5種異步實(shí)現(xiàn)方式詳解
這篇文章主要介紹了Java異步編程的5種異步實(shí)現(xiàn)方式詳解,異步編程是程序并發(fā)運(yùn)行的一種手段,它允許多個(gè)事件同時(shí)發(fā)生,當(dāng)程序調(diào)用需要長時(shí)間運(yùn)行的方法時(shí),它不會(huì)阻塞當(dāng)前的執(zhí)行流程,程序可以繼續(xù)運(yùn)行,需要的朋友可以參考下2024-01-01
關(guān)于StringUtils.isBlank()的使用及說明
這篇文章主要介紹了關(guān)于StringUtils.isBlank()的使用及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05

