Java類初始化順序詳解
Java 類初始化介紹
java語言在使用過程中最先開始就是初始化,在工作中如果遇到什么問題需 要定位往往到最后也可能是初始化的問題,因此掌握初始化的順序很重要。
根據(jù)java 語言特性,本人針對初始化中常遇到的一些關(guān)鍵點做了總結(jié),當(dāng)然是基于代碼之上的,主要針對JVM加載一個類之后,類的屬性等在內(nèi)存中的初始化,主要靜態(tài)的變量和非靜態(tài)的變量,以及靜態(tài)代碼塊,普通代碼塊等。具體參考下面的圖:
簡單介紹下圖的意思,java類對象初始化主要包括:
- 靜態(tài)基本變量;
- 靜態(tài)類變量;
- 靜態(tài)代碼塊;
- 普通基本變量;
- 普通類類型變量;
- 普通代碼塊;
- 構(gòu)造方法;
初始化的時候主要就是這些屬性,但是該類繼承自父類,則初始化順序號包括基類的這些屬性,即初始化屬性包括本類的這些屬性+父類的這些屬性,并且基類的屬性和本類的屬性交叉初始化。
無繼承關(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"); }
接下來是運行結(jié)果:
結(jié)果分析:
代碼很簡單,分別在2個類中的基本屬性,在JavaInitWithMain 類中的main方法中不做任何操作,查看結(jié)果。
根據(jù)結(jié)果可知,JVM加載了JavaInitWithMain類之后初始化了該類的屬性,順序是 靜態(tài)的—>非靜態(tài)的—->構(gòu)造方法,靜態(tài)的包括靜態(tài)的基本變量,靜態(tài)的類類型變量,靜態(tài)代碼塊,這三個的順序是 程序員的書寫順序。
得出結(jié)論:無繼承關(guān)系時的初始化順序 靜態(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)的屬性,同時為了方便查看去掉了改類中的靜態(tài)類變量和靜態(tài)類類型變量,如下: private static TheSonofTestB sonNB = new TheSonofTestB();
查看 輸出結(jié)果,如下:
同樣分析下結(jié)果: 初始化sonNB 時先去初始化其基類的靜態(tài)屬性,然后初始化TheSonofTestB的靜態(tài)屬性,接下來是父類的基本變量,父類的構(gòu)造,子類的基本變量,最后子類自己的構(gòu)造。
得出結(jié)論: 不管是本類存在繼承還是本類的類對象屬性存在繼承
在初始化時都是: 父類的靜態(tài)屬性—->子類的靜態(tài)屬性—->父類的基本類型屬性—->父類的構(gòu)造—>子類的基本屬性—->子類的構(gòu)造
寫在最后
最后我想說2點:
1:不管存在不存在繼承,靜態(tài)的屬性—>非靜態(tài)的屬性—->構(gòu)造方法 都是初始化的順序,存在繼承時,依然一樣,只不過父類和子類的這些屬性交替進行
2:思考問題: 子類如果覆蓋了父類的靜態(tài)屬性,那么調(diào)用子類的靜態(tài)屬性時,靜態(tài)屬性的值應(yīng)該是什么?子類是靜態(tài)屬性共有幾個?各位可自行試驗
到此這篇關(guān)于Java類初始化順序詳解的文章就介紹到這了,更多相關(guān)Java類初始化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring Cloud Gateway 數(shù)據(jù)庫存儲路由信息的擴展方案
這篇文章主要介紹了詳解Spring Cloud Gateway 數(shù)據(jù)庫存儲路由信息的擴展方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11Druid簡單實現(xiàn)數(shù)據(jù)庫的增刪改查方式
這篇文章主要介紹了Druid簡單實現(xiàn)數(shù)據(jù)庫的增刪改查方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07在springboot中如何使用filter設(shè)置要排除的URL
這篇文章主要介紹了在springboot中如何使用filter設(shè)置要排除的URL,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12Java Fluent Mybatis實戰(zhàn)之構(gòu)建項目與代碼生成篇上
Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。國內(nèi)又以Mybatis用的多,基于mybatis上的增強框架,又有mybatis plus和TK mybatis等。今天我們介紹一個新的mybatis增強框架 fluent mybatis2021-10-10Java基于Google zxing生成帶logo的二維碼圖片
zxing是一個開放源碼的,用java實現(xiàn)的多種格式的1D/2D條碼圖像處理庫,本文主要介紹了Java基于Google zxing生成帶logo的二維碼圖片,具有一定的參考價值,感興趣的可以了解一下2023-10-10