初始化過程(Think in java 錯誤)

class Bowl {
    Bowl(int marker) {
        System.out.println("Bowl(" + marker + ")");
    }

    void f(int marker) {
        System.out.println("f(" + marker + ")");
    }
}

class Table {
    static Bowl b1 = new Bowl(1);

    Table() {
        System.out.println("Table()");
        b2.f(1);
    }

    void f2(int marker) {
        System.out.println("f2(" + marker + ")");
    }

    static Bowl b2 = new Bowl(2);
}

class Cupboard {
    Bowl b3 = new Bowl(3);
    static Bowl b4 = new Bowl(4);

    Cupboard() {
        System.out.println("Cupboard()");
        b4.f(2);
    }

    void f3(int marker) {
        System.out.println("f3(" + marker + ")");
    }

    static Bowl b5 = new Bowl(5);
}

public class OrderOfInitialization {
    public static void main(String[] args) {
        System.out.println("Creating new Cupboard() in main");
        new Cupboard();
        System.out.println("Creating new Cupboard() in main");
        new Cupboard();
    }
}

"Bowl(1)",
"Bowl(2)",
"Table()",
"f(1)",
"Bowl(4)",
"Bowl(5)",
"Bowl(3)",
"Cupboard()",
"f(2)",
"Creating new Cupboard() in main",
"Bowl(3)",
"Cupboard()",
"f(2)",
"Creating new Cupboard() in main",
"Bowl(3)",
"Cupboard()",
"f(2)",
"f2(1)",
"f3(1)"

 第一段和第二段共有 5 處錯誤(第三版的這裏就是錯誤的,詳見原著,很明顯):此下兩段中紅色的爲錯誤。Bowl 類使你得以看到類的創建, Table 類和 Cupboard 類在它們的類定義中加入了而Bowl 類型的靜態成員。

注意,在靜態數據成員定義之前,Cupboard 類先定義了一個 Bowl 類型的非靜態成員 b3。由輸出可見,靜態初始化只有在必要時刻纔會進行。如果不創建 Table 對象,也不引用 Table.b1 或 Table.b2,那麼靜 態的 Bowl b1 和 b2 永遠都不會被創建。只有在第一個 Table對象被創建(或者第一次訪問靜態數據)的時候,它們纔會被初始化。此後,靜態對象不會再次被初始化。更正爲:Bowl 類使你得以看到類的創建, Table 類和 Cupboard 類在它們的類定義中加入了而Bowl 類型的靜態成員。注意,在靜態數據成員定義之前,Cupboard 類先定義了一個 Bowl 類型的非靜態成員 bowl3。由輸出可見,靜態初始化只有在必要時刻纔會進行。如果不創建 Table 對象,也不引用 Table.bow1 或 Table.bow2,那麼靜態的 Bowl bow1 和 bow2 永遠都不會被創建。只有在第一個 Table 對象被創建(或者第一次訪問靜態數據)的時候,它們纔會被初始化。此後,靜態對象不會再次被初始化。

Creating new Cupboard() in main
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)

 

 

 

 總結一下對象的創建過程會很有幫助。假設有個名爲 Dog 的類:

1. 當首次創建類型爲 Dog 的對象時(構造器可以看成靜態方法),或者 Dog 類的靜態方法/靜態域首次被訪問時,Java 解釋器必須查找類路徑,以定位 Dog.class 文件。

2. 然後載入 Dog.class(後面會學到,這將創建一個 Class 對象),有關靜態初始化的動作都會執行。因此,靜態初始化只在 Class 對象首次加載的時候進行一次。

3. 當你用 new Dog( )創建對象的時候,首先將在堆上爲 Dog 對象分配足夠的存儲空間。

4. 這塊存儲空間會被清零,這就自動地將 Dog 中的所有基本類型數據設置成了默認值(對數字來說就是 0,對布爾型和字符型也相同),而引用則被設置成了 null。

5. 執行所有出現於域定義處的初始化動作。

6. 執行構造器。正如你將在第 6 章中看到的,這可能會牽涉到很多動作,尤其是涉及繼承

的時候。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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