| 方式 | 關鍵 API | 是否調用構造器 | 典型場景 |
|---|---|---|---|
1. new 關鍵字 | new Class() | ✅ 是 | 最常用、最直接 |
| 2. Class.newInstance() | Class.forName(...).newInstance() | ✅ 是(無參構造器) | 早期反射、框架舊代碼 |
| 3. Constructor.newInstance() | clazz.getConstructor().newInstance() | ✅ 是(可帶參/私有) | 現代反射、Spring/Hibernate |
| 4. clone() | obj.clone() | ❌ 否 | 原型模式、拷貝對象 |
| 5. 反序列化 | ObjectInputStream.readObject() | ❌ 否 | 分布式傳輸、持久化恢復 |
運行以下測試程序,觀察構造器調用次數:
public class ObjectCreation {
public static void main(String[] args) throws Exception {
// 1. new 關鍵字
Employee emp1 = new Employee();
emp1.setName("Naresh");
// 2. Class.newInstance()
Employee emp2 = (Employee) Class.forName("pkg.Employee").newInstance();
emp2.setName("Rishi");
// 3. Constructor.newInstance()
Constructor<Employee> ctor = Employee.class.getConstructor();
Employee emp3 = ctor.newInstance();
emp3.setName("Yogesh");
// 4. clone()
Employee emp4 = (Employee) emp3.clone();
emp4.setName("Atul");
// 5. 反序列化
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"));
out.writeObject(emp4); out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
in.close();
emp5.setName("Akash");
}
}
輸出結果:
Employee Constructor Called... // emp1
Employee Constructor Called... // emp2
Employee Constructor Called... // emp3
// emp4 無輸出
// emp5 無輸出
驗證結論:方式 1-3 均調用構造器;方式 4-5 繞過構造器直接在堆上分配內存並拷貝/恢復字段。
class Employee implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private String name;
public Employee() { System.out.println("Employee Constructor Called..."); }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public Object clone() {
try { return super.clone(); }
catch (CloneNotSupportedException e) { throw new AssertionError(e); }
}
// equals/hashCode/toString 略
}
new:new + invokespecial(構造器調用)Class.newInstance():invokevirtual → 內部委託 Constructor.newInstance()Constructor.newInstance():invokevirtual(直接反射調用)clone():invokevirtual → JVM 內部 Object.clone() 為 nativereadObject():invokevirtual → 反序列化引擎直接填充字段new 或依賴注入框架(Spring)管理生命週期。Constructor.newInstance(),支援帶參構造器、私有構造器。clone() 需實現 Cloneable,注意淺拷貝陷阱。Serializable,注意 serialVersionUID 維護。理解創建對象的本質差異,有助於排查框架初始化問題、優化高併發場景物件創建、正確實現拷貝與序列化邏輯。