JAVA面試題解惑系列(一)——類的初始化順序

作者:臧圩人(zangweiren)
網址:http://zangweiren.javaeye.com

>>>轉載請註明出處! <<<

大家在去參加面試的時候,經常會遇到這樣的考題:給你兩個類的代碼,它們之間是繼承的關係,每個類裏只有構造器方法和一些變量,構造器裏可能還有一段代碼 對變量值進行了某種運算,另外還有一些將變量值輸出到控制檯的代碼,然後讓我們判斷輸出的結果。這實際上是在考查我們對於繼承情況下類的初始化順序的了 解。

我們大家都知道,對於靜態變量、靜態初始化塊、變量、初始化塊、構造器,它們的初始化順序依次是(靜態變量、靜態初始化塊)>(變量、初始化塊)>構造器。我們也可以通過下面的測試代碼來驗證這一點:

Java代碼 複製代碼
  1. public   class  InitialOrderTest {   
  2.   
  3.      // 靜態變量   
  4.      public   static  String staticField =  "靜態變量" ;   
  5.      // 變量   
  6.      public  String field =  "變量" ;   
  7.   
  8.      // 靜態初始化塊   
  9.      static  {   
  10.         System.out.println(staticField);   
  11.         System.out.println( "靜態初始化塊" );   
  12.     }   
  13.   
  14.      // 初始化塊   
  15.     {   
  16.         System.out.println(field);   
  17.         System.out.println( "初始化塊" );   
  18.     }   
  19.   
  20.      // 構造器   
  21.      public  InitialOrderTest() {   
  22.         System.out.println( "構造器" );   
  23.     }   
  24.   
  25.      public   static   void  main(String[] args) {   
  26.          new  InitialOrderTest();   
  27.     }   
  28. }  


運行以上代碼,我們會得到如下的輸出結果:

  1. 靜態變量
  2. 靜態初始化塊
  3. 變量
  4. 初始化塊
  5. 構造器


這與上文中說的完全符合。那麼對於繼承情況下又會怎樣呢?我們仍然以一段測試代碼來獲取最終結果:

Java代碼 複製代碼
  1. class  Parent {   
  2.      // 靜態變量   
  3.      public   static  String p_StaticField =  "父類--靜態變量" ;   
  4.      // 變量   
  5.      public  String p_Field =  "父類--變量" ;   
  6.   
  7.      // 靜態初始化塊   
  8.      static  {   
  9.         System.out.println(p_StaticField);   
  10.         System.out.println( "父類--靜態初始化塊" );   
  11.     }   
  12.   
  13.      // 初始化塊   
  14.     {   
  15.         System.out.println(p_Field);   
  16.         System.out.println( "父類--初始化塊" );   
  17.     }   
  18.   
  19.      // 構造器   
  20.      public  Parent() {   
  21.         System.out.println( "父類--構造器" );   
  22.     }   
  23. }   
  24.   
  25. public   class  SubClass  extends  Parent {   
  26.      // 靜態變量   
  27.      public   static  String s_StaticField =  "子類--靜態變量" ;   
  28.      // 變量   
  29.      public  String s_Field =  "子類--變量" ;   
  30.      // 靜態初始化塊   
  31.      static  {   
  32.         System.out.println(s_StaticField);   
  33.         System.out.println( "子類--靜態初始化塊" );   
  34.     }   
  35.      // 初始化塊   
  36.     {   
  37.         System.out.println(s_Field);   
  38.         System.out.println( "子類--初始化塊" );   
  39.     }   
  40.   
  41.      // 構造器   
  42.      public  SubClass() {   
  43.         System.out.println( "子類--構造器" );   
  44.     }   
  45.   
  46.      // 程序入口   
  47.      public   static   void  main(String[] args) {   
  48.          new  SubClass();   
  49.     }   
  50. }  


運行一下上面的代碼,結果馬上呈現在我們的眼前:

  1. 父類--靜態變量
  2. 父類--靜態初始化塊
  3. 子類--靜態變量
  4. 子類--靜態初始化塊
  5. 父類--變量
  6. 父類--初始化塊
  7. 父類--構造器
  8. 子類--變量
  9. 子類--初始化塊
  10. 子類--構造器


現在,結果已經不言自明瞭。大家可能會注意到一點,那就是,並不是父類完全初始化完畢後才進行子類的初始化,實際上子類的靜態變量和靜態初始化塊的初始化是在父類的變量、初始化塊和構造器初始化之前就完成了。

那麼對於靜態變量和靜態初始化塊之間、變量和初始化塊之間的先後順序又是怎樣呢?是否靜態變量總是先於靜態初始化塊,變量總是先於初始化塊就被初始化了呢?實際上這取決於它們在類中出現的先後順序。我們以靜態變量和靜態初始化塊爲例來進行說明。

同樣,我們還是寫一個類來進行測試:

Java代碼 複製代碼
  1. public   class  TestOrder {   
  2.      // 靜態變量   
  3.      public   static  TestA a =  new  TestA();   
  4.        
  5.      // 靜態初始化塊   
  6.      static  {   
  7.         System.out.println( "靜態初始化塊" );   
  8.     }   
  9.        
  10.      // 靜態變量   
  11.      public   static  TestB b =  new  TestB();   
  12.   
  13.      public   static   void  main(String[] args) {   
  14.          new  TestOrder();   
  15.     }   
  16. }   
  17.   
  18. class  TestA {   
  19.      public  TestA() {   
  20.         System.out.println( "Test--A" );   
  21.     }   
  22. }   
  23.   
  24. class  TestB {   
  25.      public  TestB() {   
  26.         System.out.println( "Test--B" );   
  27.     }   
  28. }  


運行上面的代碼,會得到如下的結果:

  1. Test--A
  2. 靜態初始化塊
  3. Test--B


大家可以隨意改變變量a、變量b以及靜態初始化塊的前後位置,就會發現輸出結果隨着它們在類中出現的前後順序而改變,這就說明靜態變量和靜態初始化塊是依照他們在類中的定義順序進行初始化的。同樣,變量和初始化塊也遵循這個規律。

瞭解了繼承情況下類的初始化順序之後,如何判斷最終輸出結果就迎刃而解了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章