首頁  >  文章  >  Java  >  淺談Java中各成員變數初始化流程

淺談Java中各成員變數初始化流程

无忌哥哥
无忌哥哥原創
2018-07-19 11:48:581665瀏覽

前言

最近在看Thinking in java,關於類別中的各成員初始化一直未曾關注,這裡記錄一下,如有錯誤,請指正:

1.繼承與初始化

#了解包含繼承的初始化全過程,以對所發生的一切有個全域性的把握,是很有益的。

在Java中,每個類別的編譯程式碼都存在於它自己的獨立的檔案中(即class檔案),而該檔案只在需要使用程式碼時才會載入。一般來說,“類別的程式碼在初次使用的時候才會載入”,這通常包含下面兩種情況:

  1. 創建類別的第一個物件的時候

  2. 存取static方法或欄位時

注意:第一次使用類別時,也是static初始化發生之處,所有物件和程式碼均依照書寫順序進行初始化,定義為static的欄位只會被初始化一次。

廢話不多說,詳細如下:

public class Base {
    //static字段
    private static int I1 = printInt("Init I1");    //普通字段
    private int i = 11;    
    protected int j;    
    public Base(){
        System.out.println("Base constructor");
        System.out.println("i="+i+" j="+j);
        j = 40;
    }    static int printInt(String str) {
        System.out.println(str);        
        return 10;
    }
}
public class Son extends Base{
    private static int I2 = printInt("Init I2");    
    public Son() {
        System.out.println("Son constructor");
        System.out.println("I2="+I2+" j= "+j);
    }    
    public static void main(String[] args) {
        Son son = new Son();
    }
}

看完這段程式碼,你覺得輸出是什麼呢?

先給答案,在來分析:

Init I1
Init I2
Base constructori=11 j=0Son constructorI2=10 j= 40

分析:

程式先從Son類別的main方法入手,於是載入器開始啟動並找出Son編譯程式碼(即class檔案)。在進行載入中發現Son還有父類Base,於是繼續載入Base的編譯程式碼(如果Base還有父類則繼續向上執行),接下來,根基類的static欄位初始化,因為子類可能會依賴基類成員能否被正確初始化,所以發生了Init I1, 然後往下到了Son,Son類別的static欄位初始化,於是發生了Init I2 ,到此所有的必要的類別載入完成,可以開始初始化物件。看到Son son = new Son()這行程式碼,準備呼叫Son的建構器,我們知道在繼承關係中,子類別的建構器中會呼叫super(),當然這裡是隱式調用。這樣又會回到父類別中去,不過在完成建構器之前,父類別(Base)中的所有普通字段(即非static字段)都會完成自己的初始化,所以會看到輸出i=11 j=0,接著來到子類別(Son),和父類別的執行過程一樣,先完成普通欄位的初始化,再呼叫建構器方法。

說了一大堆,整體流程如下:

  1. 從程式入口開始,載入該類別(這裡設為Z類別),如有繼承關係遞歸向上,直到根類別(這裡假設A類別)。

  2. 完成A類別的static欄位初始化,遞歸向下,直到遇到Z類別。

  3. 完成A類別的普通域初始化,完成A類別的建構器,遞歸向下,直到遇到Z類別。

#

以上是淺談Java中各成員變數初始化流程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn