在 Java 開發中,反射是一項強大且核心的技術,它允許程序在運行時動態獲取類的信息、創建對象、調用方法。其中,Class.forName() 是實現動態加載類的關鍵入口。本文將深入解析靜態加載與動態加載的區別,並通過實戰代碼演示如何利用反射實現靈活的類加載策略。
理解反射的前提,首先要區分「編譯時期」與「運行時期」的類加載機制:
new 關鍵字創建對象時,編譯器會在編譯階段檢查類是否存在。若類不存在,編譯直接失敗。這意味著類的依賴關係在編譯期就已固化。Class.forName("全限定類名") 在運行時根據字符串加載類。類的具體實現可以在運行時根據配置、用戶輸入或其他業務邏輯動態決定,極大地提高了系統的擴展性。假設我們需要根據命令行參數決定實例化 Word 還是 Excel 類:
package com.tsh.reflect;
class ReflectLoadDemo {
public static void main(String[] args) {
if (args[0].equals("Word")) {
Word word = new Word(); // 編譯期必須存在 Word 類
}
if (args[0].equals("Excel")) {
Excel excel = new Excel(); // 編譯期必須存在 Excel 類
}
}
}
這種寫法強制要求所有可能用到的類在編譯期就存在,無法實現「按需加載」,也難以應對插件化、模塊化等動態擴展場景。
利用反射,我們可以在真正需要時才加載類:
package com.tsh.reflect;
class ReflectLoadDemo {
public static void main(String[] args) {
if (args[0].equals("Word")) {
try {
// 動態加載類並創建實例
Class> c = Class.forName("com.tsh.reflect.Word");
c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class Word {}
優勢顯而易見:
為了讓動態加載更具工程價值,通常結合接口規範使用:
IDocument,規範 open()、save() 等行為。WordDoc、ExcelDoc、PdfDoc)實現該接口。這就是眾多框架(如 Spring、Dubbo、JDBC 驅動加載)實現「約定優於配置」、插件化擴展的核心基石。
Class.forName() 不僅是獲取 Class 對象的途徑,更是 Java 動態性的體現。掌握「編譯期靜態綁定」與「運行期動態加載」的區別,善用反射配合接口編程,能讓你設計出更靈活、可擴展、維護性更強的系統架構。