文章標題雙雙寫「靜態加載」,實際探討的是靜態載入(Static Loading)與動態載入(Dynamic Loading/反射)的對比。兩者差異在於類別載入時機與耦合程度。
直接使用 new 關鍵字建立物件,編譯階段就必須確保所有可能用到的類別存在。
package com.imooc.loading;
public class Office_Static {
public static void main(String[] args) {
// 編譯期就必須有 Word.class 和 Excel.class
if ("Word".equals(args[0])) {
Word w = new Word();
w.start();
}
if ("Excel".equals(args[0])) {
Excel e = new Excel();
e.start();
}
}
}
缺點:即使執行時只用到 Word,Excel 類別也會被載入,增加記憶體佔用;新增文件型別需修改原始碼並重新編譯,違反開放封閉原則。
利用 Class.forName() 根據字串動態載入類別,配合介面實現多態,實現「不修改原碼、熱插拔」效果。
package com.imooc.loading;
public interface OfficeAble {
void start();
}
public class Word implements OfficeAble {
public void start() { System.out.println("word start"); }
}
public class Excel implements OfficeAble {
public void start() { System.out.println("excel start"); }
}
package com.imooc.loading;
public class OfficeBetter {
public static void main(String[] args) {
try {
// 執行期指定完整類別名稱,例如 com.imooc.loading.Excel
Class> c = Class.forName(args[0]);
// 向上轉型為介面,透過介面呼叫方法
OfficeAble oa = (OfficeAble) c.getDeclaredConstructor().newInstance();
oa.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
| 特性 | 靜態載入 | 動態載入(反射) |
|---|---|---|
| 載入時機 | 編譯期/類別載入初始化階段 | 執行期按需載入 |
| 耦合度 | 強耦合,依賴具體類別 | 弱耦合,依賴介面/字串 |
| 擴充性 | 需修改原碼重編譯 | 新增實作類別即可,無需動主程式 |
| 效能 | 極快(JIT 優化) | 較慢(反射解析、存取檢查) |
| 適用場景 | 核心業務、高頻呼叫 | 外掛架構、框架開發、配置驅動 |
Constructor、Method 物件),減少重複解析開銷。靜態與動態載入無絕對優劣,關鍵在於在正確的層次做正確的選擇。掌握反射機制原理,能讓你設計出更具彈性、可維護的 Java 架構。