new 與 Class.newInstance() 都能建立物件,但底層機制、效能、適用場景截然不同。本文從 JVM 類加載、構造方法、反射效能三個維度深度對比。
| 維度 | new | Class.newInstance() |
|---|---|---|
| 類加載時機 | 首次 new 時觸發加載、連結、初始化 |
調用前類必須已加載並連結完成 |
| 構造方法 | 可呼叫任意 public 建構子(含帶參) |
僅能呼叫無參建構子 |
| 型別安全 | 編譯期強型別檢查 | 執行期才能發現型別錯誤(返回 Object) |
| 效能 | JIT 優化極好,極快 | 反射調用,慢 10~100 倍 |
| 異常處理 | 編譯期捕獲 | 需捕獲 InstantiationException、IllegalAccessException |
| 典型應用 | 日常物件建立 | 工廠模式、動態載入、框架底層 |
new 指令流程<init>(建構子)初始化物件Class.newInstance() 流程Class 物件已存在 → 類已完成加載、驗證、準備、解析、初始化SecurityManager、存取權限)public 無參建構子關鍵結論:newInstance() 要求類「已就緒」,適合類在配置檔/註解中以字串形式指定的動態場景。
ExampleInterface factory = new ConcreteImpl(); // 強型別、高效能
String className = "com.example.ConcreteImpl"; // 來自配置檔
Class> clazz = Class.forName(className); // 觸發類加載
ExampleInterface factory = (ExampleInterface) clazz.newInstance(); // 僅無參建構子
Constructor.newInstance()Java 9 已棄用 Class.newInstance(),Java 17 移除。推薦使用 Constructor 完整支援帶參建構子:
Constructor> ctor = clazz.getDeclaredConstructor(String.class, int.class);
ExampleInterface factory = (ExampleInterface) ctor.newInstance("arg", 123);
setAccessible(true) 存取私有建構子InvocationTargetException 包裝真實異常)new:型別安全、效能最佳、可讀性最高Constructor.newInstance() 替代已棄用的 Class.newInstance()