[Java]static關鍵字

通常來說,執行new創建對象時,數據存儲空間才被分配,其方法才共外界調用。(非static域和方法必須知道和它們一起運作的特定對象)
但是當聲明一個事物是static時,意味着這個域或方法不會與包含它的那個類的任何對象實例關聯在一起。

例子:
    class StaticTest{
        static int i = 47;
    }
現在,即使創建兩個StaticTest對象,StaticTest.i也只有一份存儲空間,這兩個對象共享一個i。
    StaticTest st1 = new StaticTest();
    StaticTest st2 = new StaticTest();
在這裏,st1.i和st2.i指向同一存儲空間,具有相同的值47

引用static變量有兩種方法:
  1. 通過一個對象去定位它。eg:
    st2.i;
  2. 通過其類名直接引用(這對於非靜態成員是不行的)。 eg: StaticTest.i++;

    使用類名是引用static變量的首選方式,不僅強調了static結構,在某些情況下爲編譯器進行優化提供更佳的可能。
    定義靜態方法的方式和定義靜態變量類似。static方法的重要用法就是在不創建任何對象的前提下就能調用它,這一點對於定義main()方法很重要,這個方法是運行一個應用的入口點。


靜態數據的初始化

  • 列表內容無論創建多少個對象,靜態數據都只佔用一份存儲區域。
  • 如果一個域是靜態的基本類型域,且沒有對它進行初始化,那麼它就會獲得基本類型的標準初值;如果它是一個對象引用,則默認初始化值是null。

/**
 * 類的初始化順序 1. 靜態變量 2. 定義初始化 3. 構造函數
 * 一個例子如下:
 */

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

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

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

    Table() {
        System.out.println("Table()");
        bowl2.f1(1);
    }

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

    static Bowl bowl2 = new Bowl(2);
}

class Cupboard {
    Bowl bowl3 = new Bowl(3);
    static Bowl bowl4 = new Bowl(4);

    public Cupboard() {
        System.out.println("Cupboard()");
        bowl4.f1(2);
    }

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

    static Bowl bowl5 = new Bowl(5);
}

public class StaticInitialization {
    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();
        table.f2(1);
        cupboard.f3(1);
    }

    static Table table = new Table();
    static Cupboard cupboard = new Cupboard();
}

/** Output:

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

**/

總結:
1. 靜態初始化只有在必要的時刻纔會進行,static對象首次初始化後不會再次被初始化;
2. 初始化順序:先static對象(尚未初始化過的),然後纔是非靜態對象。
3. 即使沒有顯式使用static關鍵字,構造器實際上也是靜態方法。因此首次創建類對象時(構造器可以視爲靜態方法),或對象的靜態方法/靜態域首次被訪問時,java解釋器必須查找類路徑,來定位.class文件。
4. 載入.class文件後,有關靜態初始化的所有動作都會執行(靜態初始化只在class對象首次加載時進行一次)。
5. 使用new創建對象時,首先在堆上爲對象分配足夠的存儲空間。
6. 這塊存儲空間被清零,就自動地將類對象中的所有基本類型數據都設置成了默認值(對數字、布爾值、字符型來說都是0),而引用被設置成了null。
7. 執行所有出現於字段定義中的初始化動作。
8. 執行構造器。

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