天天看點

java類初始化

我們知道一個類要被使用必須經過裝載、連接配接、初始化這樣的過程,下面先對這3個過程進行一個簡單的概述。

在裝載階段類裝載器将編譯形成的class檔案裝載禁記憶體,建立類相關的class對象,這個class對象封裝了我們要使用的類的類型資訊。

連接配接階段又可以被分為3個階段,驗證、準備、解析。

驗證就是確定java類型格式的正确性,并适于jvm使用。

準備階段,jvm為靜态變量配置設定空間,并設定預設值,這裡隻設定預設值,例如int型變量會被賦予預設值0。在這一階段,jvm可能還會為一些資料結構配置設定記憶體,目的是提高運作程式的性能,比如說方法表。

解析過程就是在類型的常量池中尋找類、接口、字段和方法的符号引用,把這些符号引用替換成直接引用。這個階段可以被推遲到初始化之後,在程式運作中真正使用某個符号引用時再去解析它。

類初始化的順序下面這個程式完整的展現出來了,而且十分易記。

class Test{
 static{
 System.out.println("父類static 塊 1 執行");
 }
 static Sample staticSam1=new Sample("父類 靜态成員staticSam1初始化");
 Sample sam1=new Sample("父類 sam1成員初始化");
 static Sample staticSam2=new Sample("父類 靜态成員staticSam2初始化");
 static{
 System.out.println("父類 static 塊 2 執行");
 }
 Test()
 {
 System.out.println("父類 Test預設構造<span id="21_nwp" style="width: auto; height: auto; float: none;"><a id="21_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=11&is_app=0&jk=46fc72f8b03d1143&k=%BA%AF%CA%FD&k0=%BA%AF%CA%FD&kdi0=0&luki=8&mcpm=0&n=10&p=baidu&q=xiaoxiaobai_cpr&rb=0&rs=1&seller_id=1&sid=43113db0f872fc46&ssp2=1&stid=9&t=tpclicked3_hc&td=1972324&tu=u1972324&u=http%3A%2F%2Fwww%2E52ij%2Ecom%2Fjishu%2Fjava%2F98821%2Ehtml&urlid=0" target="_blank" rel="external nofollow"  target="_blank" mpid="21" style="text-decoration: none;"><span style="color:#0000ff;font-size:12px;width:auto;height:auto;float:none;">函數</span></a></span>被調用");
 }
 Sample sam2=new Sample("父類 sam2成員初始化");
 }
 class TestSub extends Test
 {
 static Sample staticSamSub=new Sample("子類 靜态成員staticSamSub初始化");
 TestSub()
 {
 System.out.println("子類 TestSub 預設構造函數被調用");
 }
 Sample sam1=new Sample("子類 sam1成員初始化");
 static Sample staticSamSub1=new Sample("子類 靜态成員staticSamSub1初始化");
 static{System.out.println("子類 static 塊 執行");}
 Sample sam2=new Sample("子類 sam2成員初始化");
 }
           

  執行結果:

  父類 static 塊 1 執行

  父類 靜态成員staticSam1初始化

  父類 靜态成員staticSam2初始化

  父類 static 塊 2 執行

  --------父類靜态成員初始化

  子類 靜态成員staticSamSub初始化

  子類 靜态成員staticSamSub1初始化

  子類 static 塊 執行

  -------子類靜态成員初始化

  父類 sam1成員初始化

  父類 sam2成員初始化

  父類 Test預設構造函數被調用

  -------父類普通成員初始化和構造函數執行

  子類 sam1成員初始化

  子類 sam2成員初始化

  子類 TestSub 預設構造函數被調用

  -------父類普通成員初始化和構造函數執行

  由此得出Java初始化順序結論:

  1 繼承體系的所有靜态成員初始化(先父類,後子類)

  2 父類初始化完成(普通成員的初始化-->構造函數的調用)

  3 子類初始化(普通成員-->構造函數)

還有靜态嵌套類的初始化,當使用外部類時并不會初始化靜态嵌套類,隻有使用到内部類時才會初始化内部類。