| 維度 | new 關鍵字 | Class.newInstance() |
|---|---|---|
| 類加載要求 | 不要求類已加載,首次使用時觸發加載、鏈接、初始化 | 要求類已加載並完成初始化(否則拋 IllegalAccessException) |
| 構造器選擇 | 可調用任意 public 構造器(含帶參) | 僅能調用 public 無參構造器 |
| 類型安全 | 強類型,編譯期檢查 | 弱類型,返回 Object 需強轉 |
| 性能 | 極高(JIT 優化、無反射開銷) | 較低(反射調用、訪問檢查、異常處理) |
| 異常處理 | 編譯期捕獲語法錯誤,運行期拋 OutOfMemoryError 等 | 需捕獲 InstantiationException、IllegalAccessException |
| 典型應用場景 | 日常對象創建、已知類型 | 反射框架、工廠模式、動態加載類名(配置文件) |
// 1. new 關鍵字
User user = new User("Alice", 25); // 調用帶參構造器
// 2. Class.newInstance() - 僅無參構造器
String className = "com.example.User";
Class<?> clazz = Class.forName(className);
User user2 = (User) clazz.newInstance(); // 必須有 public User() {}
user2.setName("Bob");
user2.setAge(30);
// 3. 現代替代方案:Constructor.newInstance() (JDK 1.1+)
// 支持帶參構造器,性能優於 Class.newInstance()
Constructor<User> ctor = clazz.getConstructor(String.class, int.class);
User user3 = ctor.newInstance("Charlie", 35);
JVM 規範:newInstance() 相當於調用類的無參構造器,構造器執行前類必須完成初始化(<clinit>)。若類未初始化,JVM 會先初始化,但反射調用路徑中可能繞過某些檢查,導致狀態不一致,因此強制要求調用者確保類已初始化。
new:~1-2 ns/op(JIT 內聯後幾乎為零開銷)。Class.newInstance():~50-100 ns/op(反射開銷)。Constructor.newInstance():~30-80 ns/op(略優於 Class.newInstance)。Java 9 起 Class.newInstance() 標記為 @Deprecated(since="9"),因其繞過編譯器可訪問性檢查(可調用 private 無參構造器),安全風險高。推薦統一使用 Constructor.newInstance()。
new。Constructor.newInstance(),緩存 Constructor 對象提升性能。