首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java物件複製深度解析:淺層複製vs深層複製(序列化實作)

     編輯:Java 程式設計入門

核心差異一覽

複製類型機制參考型別欄位行為適用場景
淺層複製clone()Object.clone()逐位複製複製參考值,新舊物件共享同一參考物件全為基本型別/不可變物件(String等)
深層複製遞迴複製或序列化遞迴建立新物件,新舊物件完全獨立含可變參考型別欄位(集合、自訂物件等)

實作範例:Square類別含Point參考

public class Square implements Cloneable, Serializable {
    private Point location = new Point(0, 0); // 可變參考型別
    private float sideLength = 1F;

    // 淺層複製:預設clone()行為
    @Override
    public Object clone() {
        try { return super.clone(); }
        catch (CloneNotSupportedException e) { throw new InternalError(e); }
    }

    // 深層複製:序列化往返
    public Object deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this); // 寫入位元組流

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject(); // 讀出新物件圖
    }
    // getter/setter...
}

驗證結果解讀

Square s = new Square();
s.setSideLength(2);
s.setLocation(new Point(2, 5));

Square shallow = (Square) s.clone();
Square deep = (Square) s.deepClone();

// 修改原物件參考欄位
s.getLocation().x = 99;

// 淺層複製受影響
System.out.println(shallow.getLocation().x); // 99 ⚠️ 共享同一Point

// 深層複製獨立
System.out.println(deep.getLocation().x);    // 2 ✅ 獨立副本

深層複製三大實作策略比較

  1. 序列化法(本例):通用、簡潔,要求所有物件implements Serializable,效能較低(I/O開銷),不支援transient欄位邏輯。
  2. 手動遞迴複製:在clone()中new Point(this.location.x, this.location.y),效能最佳、可控性最高,但維護成本隨物件圖複雜度上升。
  3. 第三方庫:Apache Commons Lang SerializationUtils.clone()、Dozer、MapStruct等,生產環境建議採用成熟庫。

最佳實務建議

  • 優先使用不可變物件(如String、LocalDate、GuavaImmutableList),從根源消除深複製需求
  • 若必須可變,建構子/工廠方法回傳防禦性副本
  • 實作Cloneable時務必覆寫clone()並呼叫super.clone(),處理參考欄位深複製
  • 序列化法適用於物件圖結構固定、效能非瓶頸、跨JVM傳輸場景
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved