Java 虛擬機規範定義類加載過程為:加載 → 驗證 → 準備 → 解析 → 初始化 → 使用 → 卸載。其中準備階段為靜態字段分配內存並設置默認值,初始化階段執行 <clinit>() 類構造器(靜態變量賦值+靜態代碼塊,按源碼順序)。
public class StaticTest {
public static void main(String[] args) {
staticFunction();
}
static StaticTest st = new StaticTest(); // ①
static { System.out.println("1"); } // ②
{ System.out.println("2"); } // ③ 實例代碼塊
StaticTest() { // ④ 構造器
System.out.println("3");
System.out.println("a=" + a + ",b=" + b);
}
public static void staticFunction() { // ⑤
System.out.println("4");
}
int a = 110; // ⑥ 實例變量
static int b = 112; // ⑦ 靜態變量
}
2 3 a=110,b=0 1 4
main 調用 staticFunction() → 觸發 StaticTest 類初始化;st=null、b=0(默認值),a 不分配(非靜態);st = new StaticTest() → 嵌套觸發實例初始化:a=110(⑥)b 仍為默認值 0 → 輸出 a=110,b=0b=112(但無打印);main 繼續執行 ⑤:打印 4。new 當前類() 時,實例初始化插入到類初始化流程中;<clinit>();<clinit>(),順序=源碼順序;static final int b=112 準備期即為 112,非常量準備期為默認值。public class Test {
public static void main(String[] args) { func(); }
static Test st = new Test(); // 嵌套實例化
static void func() {}
}
執行流程:main → 類初始化 → st賦值觸發實例化 → 實例初始化完成 → 類初始化結束。若構造器中訪問靜態字段,可能看到默認值。
-XX:+TraceClassLoading 觀察類加載順序調試複雜依賴。