Class.forName 核心作用
Class.forName(String className) 請求 JVM查找、載入、鏈接、初始化指定類,返回 Class 對象。關鍵點:
- 觸發類的靜態初始化器(
static {} 塊)執行。
- 不創建實例,僅完成類級別的初始化。
- 異常:
ClassNotFoundException(類路徑找不到)、NoClassDefFoundError(依賴類缺失)。
動態實例化:newInstance()
String className = "com.example.MyClass"; // 來自配置/用戶輸入
Class> clazz = Class.forName(className);
Object instance = clazz.getDeclaredConstructor().newInstance(); // 推薦 JDK 9+
// 舊寫法:clazz.newInstance() // 已棄用,僅能調用無參公共構造器
newInstance() vs new 關鍵字
| 維度 | newInstance() | new |
| 類型檢查 | 弱類型(運行時) | 強類型(編譯時) |
| 構造器要求 | 無參 + public | 任意可見構造器 |
| 性能 | 較低(反射開銷) | 高(直接調用) |
| 用途 | 框架/插件/配置驅動 | 常規業務代碼 |
工廠模式結合:解耦實現類
// 配置文件 config.xml: com.example.impl.ServiceImpl
String className = readFromXmlConfig(); // 動態讀取
Class> clazz = Class.forName(className);
MyInterface service = (MyInterface) clazz.getDeclaredConstructor().newInstance();
// 後續使用 service 接口,無需知道具體實現類
優勢:更換實現類只需修改配置,代碼零修改,符合開閉原則。
JDBC 驅動載入機制
為什麼只需 Class.forName()?
JDBC 規範要求驅動類在靜態初始化塊中向 DriverManager 註冊自身:
public class MyJDBCDriver implements Driver {
static {
DriverManager.registerDriver(new MyJDBCDriver());
}
// 實現 Driver 接口方法...
}
因此 Class.forName("com.mysql.jdbc.Driver") 觸發靜態塊 → 完成註冊,後續 DriverManager.getConnection() 即可找到驅動。無需 newInstance()。
JDBC 4.0+ (JDK 6+) 自動載入
若驅動 JAR 包含 META-INF/services/java.sql.Driver 文件,DriverManager 會通過 ServiceLoader 自動發現,**無需顯式 Class.forName()**。
JVM 視角:類加載流程
- 載入:讀取 .class 字節碼,生成
Class 對象(啟動類加載器/擴展/應用)。
- 鏈接:驗證、準備(靜態字段賦默認值)、解析(符號引用→直接引用)。
- 初始化:執行
static 塊、靜態字段賦值語句(Class.forName 保證完成此階段)。
總結
Class.forName() 是動態類載入的入口,核心價值在於觸發靜態初始化。
- 配合反射實例化(
getDeclaredConstructor().newInstance())實現插件化架構。
- JDBC 歷史遺留用法
Class.forName(driver) 本質是利用靜態塊副作用,現代版本已可省略。
- 上一篇文章: Python 安裝 MySQLdb 驅動程式完整教學(Windows 與 Linux)
- 下一篇文章: Java 異常處理核心概念與最佳實踐:try-catch-finally、異常鏈與資源釋放
Copyright ©
程式碼之家 All Rights Reserved