Java 初始化順序

來源:互聯網
上載者:User

標籤:java   java學習   java面試題   

Java初始化(initialization)其實包含兩部分:
1.類的初始化(initialization class & interface)
2.對象的建立(creation of new class instances)。
因為類的初始化其實是類載入(loading of classes)的最後一步,所以很多書中把它歸結為“對象的建立”的第一步。其實只是看問題的角度不同而已。為了更清楚的理解,這裡還是分開來。

順序:
應為類的載入肯定是第一步的,所以類的初始化在前。大體的初始化順序是:
類初始化 -> 子類建構函式 -> 父類建構函式 -> 執行個體化成員變數 -> 繼續執行子類建構函式的語句

下面結合例子,具體解釋一下。
1。類的初始化(Initialization classes and interfaces),其實很簡單,具體來說有:
(a)初始化類(initialization of class),是指初始化static field 和執行static初始化塊。
例如:
  1. class Super {

  2.         static String s = “initialization static field”; //初始化static field,其中“= “initialization static field” ”又叫做static field initializer


  3.         // static初始化塊,又叫做static initializer,或 static initialization block

  4.         static {

  5.         System.out.println(“This is static initializer”);

  6. }

  7. }

複製代碼

btw,有些書上提到static initializer 和 static field initializer 的概念,與之對應的還有 instance initializer 和 instance variable initializer。例子中的注釋已經解釋了其含義。

(b)初始化介面(initialization of interface),是指初始化定義在該interface中的field。

*注意*
--initialization classes 時,該class的superclass 將首先被初始化,但其實現的interface則不會。
--initialization classes 時,該class的superclass,以及superlcass的superclass 會首先被遞迴地初始化,一直到java.lang.Object為止。但initialiazation interface的時候,卻不需如此,只會初始化該interface本身。
--對於由引用類變數(class field)所引發的初始化,只會初始化真正定義該field的class。
--如果一個static field是編譯時間常量(compile-time constant),則對它的引用不會引起定義它的類的初始化。

為了協助理解最後兩點,請試試看下面的例子:
  1. public class Initialization {

  2.         

  3.         public static void main(String[] args) {

  4.                 

  5.                 System.out.println(Sub.x); // Won‘t cause initialization of Sub, because x is declared by S, not Sub.

  6.                                          // 不會引起Sub類的初始化,因為x是定義在Super類中的

  7.                 System.out.println("-------------------------");

  8.                 System.out.println(Sub.y); // Won‘t cause initialization of Sub, because y is constant.

  9.                                          // 不會引起Sub類的初始化,因為y是常量

  10.                 System.out.println("-------------------------");

  11.                 System.out.println(Sub.z = 2004); // Will cause initialization of Sub class

  12. // 將會引起Sub的初始化

  13.         }

  14. }


  15. class Super{

  16.         static int x = 2006;

  17. }


  18. class Sub extends Super {

  19.         

  20.         static final int y = 2005;

  21.         

  22. static int z;

  23.         

  24. static {

  25.                 System.out.println("Initialization Sub");

  26.         }

  27. }


複製代碼

2。對象的建立(creation of new class instances),稍微有點煩瑣,具體的步驟如下
(a) 所有的成員變數—包括該類,及它的父類中的成員變數--被分配記憶體空間,並賦予預設值。(Btw,這裡是第一次初始化成員變數)
(b) 為所調用的建構函式初始化其參數變數。(如果有參數)
(c) 如果在建構函式中用this 調用了同類中的其他建構函式,則按照步驟(b)~(f)去處理被調用到的建構函式。
(d) 如果在建構函式中用super調用了其父類的建構函式,則按照步驟(b)~(f)去處理被調用到的父類建構函式。
(e) 按照書寫順序,執行instance initializer 和 instance variable initializer來初始化成員變數。(Btw,這裡是第二次初始化成員變數)
(f) 按照書寫順序,執行constructor的其餘部分。

*注意*
成員變數其實都被初始化2次,第一次是賦予預設值,第二次才是你想要設定的值。

最後看一個例子:
  1. public class InitializationOrder {


  2.         public static void main(String[] args) {

  3.                 Subclass sb = new Subclass();

  4.         }

  5. }


  6. class Super{

  7.         

  8.         static {

  9.                 System.out.println(1);

  10.         }

  11.         

  12.         Super(int i){

  13.                 System.out.println(i);

  14.         }

  15. }


  16. class Subclass extends Super implements Interface{

  17.         

  18.         static {

  19.                 System.out.println(2);

  20.         }        

  21.         

  22.         Super su = new Super(4);

  23.         

  24.         Subclass() {

  25.                 super(3);

  26.                 new Super(5);

  27.         }

  28. }


  29. interface Interface{

  30.         static Super su = new Super(0);

  31. }


複製代碼

稍微解釋一下:
首先,Java虛擬機器要執行InitializationOrder類中的static 方法main(),這引起了類的初始化。開始初始化InitializationOrder類。具體的步驟略去不說。
接著,InitializationOrder類初始化完畢後,開始執行main()方法。語句Subclass sb = new Subclass()將建立一個Subclass對象。載入類Subclass後對其進行類初始化,但因為Subclass有一個父類Super,所以先初始化Super類,初始化塊static {System.out.println(1);}被執行,列印輸出1;
第三,Super初始化完畢後,開始初始化Subclass類。static {System.out.println(2);}被執行,列印輸出2;
第四,至此,類的載入工作全部完成。開始進入建立Subclass的對象過程。先為Subclass類和其父類Super類分配記憶體空間,這時Super su 被附值為null;
第五,執行建構函式Subclass()時,super(3)被執行。如前面(d)所說,Super類的建構函式Super(int i){….}被調用,並按照步驟(b)~(f)來處理。因此,遞迴調用Super類的父類Object類的建構函式,並按照步驟(b)~(f)來初始化Object類,不過沒有任何輸入結果。最後列印輸出3;
第六,如前面(e)所說,初始化成員變數su,其結果是列印輸出4;
第七,如前面(f)所說,執行new Super(5),並列印輸出5;
最後,Subclass雖然實現了介面Interface,但是初始化它的時候並不會引起介面的初始化,所以介面Interface中的static Super su = new Super(0)自始至終都沒有被執行到。

① 類屬性 (靜態變數) 定義時的初始化,如上例的 static String a = "string-a";
    ② static 塊中的初始化代碼,如上例 static {} 中的 b = "string-b";
    ③ 對象屬性 (非靜態變數) 定義時的初始化,如上例的 String c = "stirng-c";
    ④ 構造方法 (函數) 中的初始化代碼,如上例構造方法中的 d = "string-d";


Java 初始化順序

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.