訪問類的靜態屬性與類的加載

訪問類的靜態屬性與類的加載


今工作遇到很多這樣的加載,因而找其原由

1. 訪問類的靜態變量

現有SuperClass類,其源碼如下:

public class SuperClass {
    public static String staticVariable = "staticVariable";
    public static final String STATIC_CONSTANT = "STATIC_CONSTANT";

    static {
        System.out.println("SuperClass is loading.");
    }
}

現有一段代碼,訪問SuperClass類中的靜態變量staticVariable:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        // 訪問類的靜態變量
        System.out.println(SuperClass.staticVariable);
    }
}

上述代碼執行後,控制檯輸出爲:

MainClass is loading.
SuperClass is loading.
staticVariable

從代碼的執行結果看,對類的靜態變量的引用將會觸發類的初始化過程

2. 訪問類的靜態常量

現有一段代碼,訪問SuperClass類中的靜態常量STATIC_CONSTANT:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        // 訪問類的靜態常量
        System.out.println(SuperClass.STATIC_CONSTANT);
    }
}

上述代碼執行後,控制檯輸出爲:

MainClass is loading.
STATIC_CONSTANT

從代碼的指定結果看,對類的靜態常量的引用不會觸發類的初始化過程

從源碼看,MainClass類直接引用了SuperClass類的靜態常量,但經過編譯階段的“常量傳播優化”後,該靜態常量的值“STATIC_CONSTANT”已經被存儲到了MainClass類自己的常量池中,MainClass類對該靜態常量的引用也被修改成了對自身常量池的引用。換句話說,經過編譯後,MainClass類與SuperClass類已經不存在任何聯繫了,MainClass類的字節碼文件中,不存在SuperClass類的符號引用入口。

3. 訪問父類的靜態變量

現有SuperClass類的子類SubClass,其源碼如下:

public class SubClass extends SuperClass{
    static {
        System.out.println("SubClass is loading.");
    }
}

現有一段代碼,通過SubClass類調用SuperClass類的靜態變量:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        // 調用父類的靜態變量
        System.out.println(SubClass.staticVariable);
    }
}

上述代碼執行後,控制檯輸出爲:

MainClass is loading.
SuperClass is loading.
staticVariable

從上述代碼的執行結果看,通過子類引用父類的靜態變量,並沒有觸發子類的初始化過程。其實,Java虛擬機規範中並未明確規定,對父類靜態變量的引用是否要觸發子類的初始化,這是由具體的虛擬機實現來決定的。

在上述代碼的基礎上,添加語句輸出代碼運行時的虛擬機環境信息:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        System.out.println(SubClass.staticVariable);
        System.out.println("Java 虛擬機實現名稱:" + System.getProperty("java.vm.name"));
        System.out.println("Java 虛擬機實現版本:" + System.getProperty("java.vm.version"));
    }
}
MainClass is loading.
SuperClass is loading.
staticVariable
Java 虛擬機實現名稱:Java HotSpot(TM) 64-Bit Server VM
Java 虛擬機實現版本:25.171-b11

從控制檯輸出可以看出,當前我使用的是HotSpot虛擬機。

4. 訪問父類的靜態常量

現有一段代碼,通過SubClass類訪問父類SuperClass類的靜態常量:

public class MainClass {
    static {
        System.out.println("MainClass is loading.");
    }

    public static void main(String[] args) {
        System.out.println(SubClass.STATIC_CONSTANT);
    }
}

代碼執行後的控制檯輸出:

MainClass is loading.
STATIC_CONSTANT

從上述代碼的執行結果,與上文“ 2. 訪問類的靜態常量 ”處代碼的執行結果相同。

如此更纖細明白了類的加載過程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章