摘要:對(duì)子類成員數(shù)據(jù)按照它們聲明的順序初始化,執(zhí)行子類構(gòu)造函數(shù)的其余部分。參考類的初始化順序引了大半類加載的時(shí)機(jī)
jvm系列
垃圾回收基礎(chǔ)
JVM的編譯策略
GC的三大基礎(chǔ)算法
GC的三大高級(jí)算法
GC策略的評(píng)價(jià)指標(biāo)
JVM信息查看
GC通用日志解讀
jvm的card table數(shù)據(jù)結(jié)構(gòu)
Java類初始化順序
Java對(duì)象結(jié)構(gòu)及大小計(jì)算
Java的類加載機(jī)制
Java對(duì)象分配簡(jiǎn)要流程
年老代過大有什么影響
Survivor空間溢出實(shí)例
關(guān)于Object=null
Java線程與Xss
序本文主要演示Java類的初始化順序
初始化順序對(duì)于靜態(tài)變量、靜態(tài)初始化塊、變量、初始化塊、構(gòu)造器,它們的初始化順序依次是(靜態(tài)變量、靜態(tài)初始化塊)>(變量、初始化塊)>構(gòu)造器。
實(shí)例代碼public class InitialOrderTest { /* 靜態(tài)變量 */ public static String staticField = "靜態(tài)變量"; /* 變量 */ public String field = "變量"; /* 靜態(tài)初始化塊 */ static { System.out.println( staticField ); System.out.println( "靜態(tài)初始化塊" ); } /* 初始化塊 */ { System.out.println( field ); System.out.println( "初始化塊" ); } /* 構(gòu)造器 */ public InitialOrderTest() { System.out.println( "構(gòu)造器" ); } public static void main( String[] args ) { new InitialOrderTest(); } }輸出
運(yùn)行以上代碼,我們會(huì)得到如下的輸出結(jié)果:
靜態(tài)變量
靜態(tài)初始化塊
變量
初始化塊
構(gòu)造器
繼承的情況 實(shí)例代碼class Parent { /* 靜態(tài)變量 */ public static String p_StaticField = "父類--靜態(tài)變量"; /* 變量 */ public String p_Field = "父類--變量"; protected int i = 9; protected int j = 0; /* 靜態(tài)初始化塊 */ static { System.out.println( p_StaticField ); System.out.println( "父類--靜態(tài)初始化塊" ); } /* 初始化塊 */ { System.out.println( p_Field ); System.out.println( "父類--初始化塊" ); } /* 構(gòu)造器 */ public Parent() { System.out.println( "父類--構(gòu)造器" ); System.out.println( "i=" + i + ", j=" + j ); j = 20; } } public class SubClass extends Parent { /* 靜態(tài)變量 */ public static String s_StaticField = "子類--靜態(tài)變量"; /* 變量 */ public String s_Field = "子類--變量"; /* 靜態(tài)初始化塊 */ static { System.out.println( s_StaticField ); System.out.println( "子類--靜態(tài)初始化塊" ); } /* 初始化塊 */ { System.out.println( s_Field ); System.out.println( "子類--初始化塊" ); } /* 構(gòu)造器 */ public SubClass() { System.out.println( "子類--構(gòu)造器" ); System.out.println( "i=" + i + ",j=" + j ); } /* 程序入口 */ public static void main( String[] args ) { System.out.println( "子類main方法" ); new SubClass(); } }輸出
父類--靜態(tài)變量
父類--靜態(tài)初始化塊
子類--靜態(tài)變量
子類--靜態(tài)初始化塊
子類main方法
父類--變量
父類--初始化塊
父類--構(gòu)造器
i=9, j=0
子類--變量
子類--初始化塊
子類--構(gòu)造器
i=9,j=20
子類的靜態(tài)變量和靜態(tài)初始化塊的初始化是在父類的變量、初始化塊和構(gòu)造器初始化之前就完成了。靜態(tài)變量、靜態(tài)初始化塊,變量、初始化塊初始化了順序取決于它們?cè)陬愔谐霈F(xiàn)的先后順序。
分析(1)訪問SubClass.main(),(這是一個(gè)static方法),于是裝載器就會(huì)為你尋找已經(jīng)編譯的SubClass類的代碼(也就是SubClass.class文件)。在裝載的過程中,裝載器注意到它有一個(gè)基類(也就是extends所要表示的意思),于是它再裝載基類。不管你創(chuàng)不創(chuàng)建基類對(duì)象,這個(gè)過程總會(huì)發(fā)生。如果基類還有基類,那么第二個(gè)基類也會(huì)被裝載,依此類推。
(2)執(zhí)行根基類的static初始化,然后是下一個(gè)派生類的static初始化,依此類推。這個(gè)順序非常重要,因?yàn)榕缮惖摹皊tatic初始化”有可能要依賴基類成員的正確初始化。
(3)當(dāng)所有必要的類都已經(jīng)裝載結(jié)束,開始執(zhí)行main()方法體,并用new SubClass()創(chuàng)建對(duì)象。
(4)類SubClass存在父類,則調(diào)用父類的構(gòu)造函數(shù),你可以使用super來指定調(diào)用哪個(gè)構(gòu)造函數(shù)。基類的構(gòu)造過程以及構(gòu)造順序,同派生類的相同。首先基類中各個(gè)變量按照字面順序進(jìn)行初始化,然后執(zhí)行基類的構(gòu)造函數(shù)的其余部分。
(5)對(duì)子類成員數(shù)據(jù)按照它們聲明的順序初始化,執(zhí)行子類構(gòu)造函數(shù)的其余部分。
類初始化public class ClinitDemo { /** * 父類中定義的靜態(tài)語句塊要優(yōu)于子類的變量賦值操作 * JVM保證一個(gè)類的clinit方法在多線程中被正確加鎖、同步 */ static class Parent { public static int A = 1; static { A = 2; } } static class Sub extends Parent { public static int B = A; } public static void main(String[] args) { System.out.println(Sub.B); } }
輸出2
static變量public class Test { static { i = 0; // 給變量復(fù)制可以正常編譯通過 // System.out.print(i); // 這句編譯器會(huì)提示“非法向前引用” } static int i = 1; static int j = 1; static{ j = 2; } public static void main(String[] args){ System.out.println(Test.i); //1 System.out.println(Test.j); //2 } }不觸發(fā)初始化實(shí)例 實(shí)例一二
/** * 被動(dòng)使用類字段演示一: * 通過子類引用父類的靜態(tài)字段,不會(huì)導(dǎo)致子類初始化 **/ class SuperClass { static { System.out.println("SuperClass init!"); } public static int value = 123; } class SubClass extends SuperClass { static { System.out.println("SubClass init!"); } } /** * 非主動(dòng)使用類字段演示 **/ public class NotInitialization { public static void main(String[] args) { // System.out.println(SubClass.value); //SuperClass init! //123 /** * 被動(dòng)使用類字段演示二: * 通過數(shù)組定義來引用類,不會(huì)觸發(fā)此類的初始化 **/ SuperClass[] sca = new SuperClass[10]; }實(shí)例三
/** * 被動(dòng)使用類字段演示三: * * 常量在編譯階段會(huì)存入調(diào)用類的常量池中,本質(zhì)上沒有直接引用到定義常量的類, * 因此不會(huì)觸發(fā)定義常量的類的初始化。 **/ public class ConstClass { static { System.out.println("ConstClass init!"); } public static final String HELLOWORLD = "hello world"; } public class Test { public static void main(String[] args){ System.out.println(ConstClass.HELLOWORLD); } }
輸出
hello world
這里沒有初始化ConstClass類,是因?yàn)樵诰幾g的時(shí)候,常量(static final 修飾的)會(huì)存入調(diào)用類的常量池【這里說的是main函數(shù)所在的類的常量池】,調(diào)用的時(shí)候本質(zhì)上沒有引用到定義常量的類,而是直接訪問了自己的常量池。
參考java類的初始化順序(引了大半)
Java類加載的時(shí)機(jī)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/65547.html
摘要:也就是說,一個(gè)實(shí)例變量,在的對(duì)象初始化過程中,最多可以被初始化次。當(dāng)所有必要的類都已經(jīng)裝載結(jié)束,開始執(zhí)行方法體,并用創(chuàng)建對(duì)象。對(duì)子類成員數(shù)據(jù)按照它們聲明的順序初始化,執(zhí)行子類構(gòu)造函數(shù)的其余部分。 類的拷貝和構(gòu)造 C++是默認(rèn)具有拷貝語義的,對(duì)于沒有拷貝運(yùn)算符和拷貝構(gòu)造函數(shù)的類,可以直接進(jìn)行二進(jìn)制拷貝,但是Java并不天生支持深拷貝,它的拷貝只是拷貝在堆上的地址,不同的變量引用的是堆上的...
摘要:在面向?qū)ο蟮某绦蛟O(shè)計(jì)語言中,多態(tài)是繼數(shù)據(jù)抽象和繼承之后的第三種基本特征。 在面向?qū)ο蟮某绦蛟O(shè)計(jì)語言中,多態(tài)是繼數(shù)據(jù)抽象和繼承之后的第三種基本特征。 1.再論向上轉(zhuǎn)型 多態(tài)作用:消除類型之間的耦合關(guān)系. 2.轉(zhuǎn)機(jī) 綁定:將一個(gè)方法調(diào)用同一個(gè)方法主體關(guān)聯(lián)起來. 前期綁定:在程序執(zhí)行前就進(jìn)行綁定(面向過程語言默認(rèn)綁定方式). 后期綁定:也叫動(dòng)態(tài)綁定或運(yùn)行時(shí)綁定,在運(yùn)行時(shí)根據(jù)對(duì)象的類型進(jìn)行綁...
摘要:先說結(jié)論對(duì)于具有繼承關(guān)系的類,它們的類和對(duì)象構(gòu)造順序?yàn)楦割惖念悩?gòu)造器子類的類構(gòu)造器父類成員變量的賦值和實(shí)例代碼塊父類的構(gòu)造函數(shù)子類成員變量的賦值和實(shí)例代碼塊子類的構(gòu)造函數(shù)。類實(shí)例塊是放在該類構(gòu)造函數(shù)最前面和父類構(gòu)造函數(shù)之后執(zhí)行的。 先說結(jié)論對(duì)于具有繼承關(guān)系的類,它們的類和對(duì)象構(gòu)造順序?yàn)椋焊割惖念悩?gòu)造器() -> 子類的類構(gòu)造器() -> 父類成員變量的賦值和實(shí)例代碼塊 -> 父類的構(gòu)造...
摘要:二驗(yàn)證驗(yàn)證主要是為了確保文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)的自身安全。五初始化類的初始化階段是類加載過程的最后一步,該階段才真正開始執(zhí)行類中定義的程序代碼或者說是字節(jié)碼。 關(guān)注我,每天三分鐘,帶你輕松掌握一個(gè)Java相關(guān)知識(shí)點(diǎn)。 虛擬機(jī)(JVM)經(jīng)常出現(xiàn)在我們面試中,但是工作中卻很少遇到,導(dǎo)致很多同學(xué)沒有去了解過。其實(shí)除了應(yīng)付面試,作為java程序員,了解...
摘要:沒有關(guān)鍵字修飾的如實(shí)例變量非靜態(tài)變量非靜態(tài)代碼塊初始化實(shí)際上是會(huì)被提取到類的構(gòu)造器中被執(zhí)行的,但是會(huì)比類構(gòu)造器中的代碼塊優(yōu)先執(zhí)行到,非靜態(tài)實(shí)例變量非靜態(tài)代碼塊的地位是相等的,它們將按順序被執(zhí)行。 閱讀原文:Java代碼執(zhí)行順序 程序中代碼執(zhí)行的順序非常重要,稍有不慎便會(huì)是程序運(yùn)行出錯(cuò),那么我將結(jié)合實(shí)例來分析代碼中的執(zhí)行。 名詞解釋 首先了解幾個(gè)名詞: 非靜態(tài)代碼塊 直接由 { } 包起...
閱讀 2618·2023-04-26 00:57
閱讀 973·2021-11-25 09:43
閱讀 2284·2021-11-11 16:55
閱讀 2363·2019-08-30 15:53
閱讀 3654·2019-08-30 15:52
閱讀 1529·2019-08-30 14:10
閱讀 3435·2019-08-30 13:22
閱讀 1263·2019-08-29 11:18