類加載中的屬性問題
舉三個例子來說明:
要準備的代碼
package com.lhc.load;
public class SuperClass {
static {
System.out.println("SuperClass init");
}
public static int value = 123;
}
package com.lhc.load;
public class SubClass extends SuperClass{
static {
System.out.println("SubClass init");
}
}
第一個例子
@Test
public void extendsTest(){
System.out.println(SubClass.value);
}
上述代碼運行之後,只會輸出“SuperClass init!",而不會輸出“SubClass init!".對於靜態字段,
只有直接定義這個字段的類纔會被初始化,因此通過其子類來引用父類中定義的靜態字段,只會觸發父類
的初始化而不會觸發子類的初始化。至於是否要觸發子類的加載和驗證,在虛擬機規範中並未明確規定,
這點取決於虛擬機的具體實現。對於Sun HotSpot虛擬機來說,可通過-XX:+TraceClassLoading參
數觀察到此操作會導致子類的加載。
第二個例子
@Test
public void arrayTest(){
SuperClass[] array = new SuperClass[10];
}
上述代碼運行之後,沒有輸出“SuperClass init!",說明並沒有觸發類SuperClass的初始化階段。
第三個例子
@Test
public void constTest(){
System.out.println(ConstClass.value);
}
上述代碼運行之後,沒有輸出“ConstClass init!",這是因爲雖然在Java源碼中引用了ConstClass類中
的常量VALUE,但其實在編譯階段通過常量傳播優化,已經將此常量的值"HelloWorld"存儲到了測試主類的
常量池中,以後測試主類對常量ConstClass.VALUE的引用實際都被轉化爲測試主類對自身常量池的引用了。
也就是說,實際上測試主類的Class文件之中並沒有CostClass類的符號引用入口,這兩個類在編譯成
Class之後就不存在任何聯繫了。