首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 類初始化深度解析:加載、連接、初始化三階段與主動使用觸發條件

     編輯:Java 綜合教學

類加載全流程

  1. 加載:類加載器讀取 .class 字節碼 → 方法區生成 Class 對象(反射入口)。
  2. 連接:
    • 驗證:字節碼格式、語義合法性。
    • 準備:為 靜態字段 分配內存並賦 默認值(0/false/null)。
    • 解析:常量池符號引用 → 直接引用(可延遲到首次使用)。
  3. 初始化:執行 <clinit>()(靜態變量賦值語句 + 靜態代碼塊,按源碼順序),父類先於子類。

主動使用觸發初始化(6 種)

  1. new 創建實例
  2. 調用靜態方法
  3. 讀/寫 非常量 靜態字段(final static 基本類型/字符串為常量,編譯期常量池化,不觸發)
  4. 反射 Class.forName()、Method.invoke()
  5. 初始化子類(觸發父類初始化)
  6. 啟動主類(含 main)

代碼驗證:初始化順序

class Base {
    int a; static int b; static int c = 1;
    static { b = 2; c = 3; System.out.println("Base static block"); }
}
class Derived extends Base {
    int d; static int e = 4;
    static { e = 5; System.out.println("Derived static block"); }
}
public class Demo {
    static int f; static { f = 100; System.out.println("Demo static block, f=" + f); }
    public static void main(String[] args) {
        System.out.println("main start");
        new Derived().display();
    }
}
// 輸出順序:
// Demo static block, f=100
// Base static block
// Derived static block
// main start
// ...

關鍵細節

  • 接口初始化:不要求父接口初始化,只有真正使用到的靜態字段才觸發該接口初始化。
  • final static 常量(編譯期常量)直接內聯到調用處字節碼,不觸發類初始化。
  • 類加載器雙親委派:Bootstrap → Extension → Application → Custom,保證核心類安全。
  • Class.forName("xxx", true, loader) 參數 true 表示初始化,false 僅加載。

實戰意義

  • 單例模式靜態內部類寫法利用類初始化線程安全特性實現延遲加載。
  • JDBC 驅動註冊 Class.forName("com.mysql.jdbc.Driver") 觸發靜態塊向 DriverManager 註冊。
  • 排查 NoClassDefFoundError vs ClassNotFoundException:前者初始化失敗,後者加載找不到。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved