利用 Java 序列化機制,將物件寫入位元組流再讀出,實現完全獨立的深層複製。要求物件及其所有引用欄位實作 Serializable 介面。
import java.io.*;
public class DepthClone {
public final static Object objectCopy(Object oldObj) {
Object newObj = null;
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(oldObj);
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
newObj = oi.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return newObj;
}
}
import java.io.Serializable;
public class SimpleClone implements Cloneable, Serializable {
private static final long serialVersionUID = -7552721152118950502L;
public String s = null;
public Object o = null;
public CloneObject cloneObject = null;
public SimpleClone(CloneObject cloneObject) {
this.cloneObject = cloneObject;
}
@Override
public Object clone() {
SimpleClone newSimpleClone = null;
try {
newSimpleClone = (SimpleClone) super.clone(); // 淺層複製
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return newSimpleClone;
}
}
public class CloneObject implements Serializable {
private static final long serialVersionUID = 4332788486669750696L;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
public class TestClone {
public static void main(String[] arg) {
CloneObject obj1 = new CloneObject();
obj1.setName("cloneOne");
CloneObject obj2 = new CloneObject();
obj2.setName("cloneTwo");
SimpleClone simpleClone1 = new SimpleClone(obj1);
SimpleClone simpleClone2 = new SimpleClone(obj2);
simpleClone1.s = "simpleClone1";
simpleClone1.o = "simpleClone1Object";
// 使用深層複製
simpleClone2 = (SimpleClone) DepthClone.objectCopy(simpleClone1);
// 修改副本的引用物件屬性
simpleClone2.cloneObject.setName("cloneThree");
System.out.println(simpleClone1.cloneObject.getName()); // 輸出 cloneOne,未受影響
System.out.println(simpleClone2.cloneObject.getName()); // 輸出 cloneThree
}
}
simpleClone1.cloneObject 仍為 "cloneOne",simpleClone2.cloneObject 為 "cloneThree",兩者完全獨立。simpleClone1.clone()),兩者共用同一 CloneObject,修改副本會導致原物件同步變更。clone() 中逐欄位 new 新物件,效能最佳但程式碼繁瑣。SerializationUtils.clone()、Gson/Jackson JSON 序列化、Kryo、MapStruct 等。public Foo(Foo other) 手動深層複製各欄位。| 場景 | 推薦方案 |
|---|---|
| 簡單物件圖、效能敏感 | 手動複製或複製建構子 |
| 複雜物件圖、含第三方類別、原始碼不可改 | 序列化法或第三方庫(Kryo 最快) |
| Web 專案常見 DTO/VO 轉換 | MapStruct 編譯期生成、或 JSON 序列化 |