訪問類的靜態屬性與類的加載
今工作遇到很多這樣的加載,因而找其原由
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. 訪問類的靜態常量 ”處代碼的執行結果相同。