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

Java 深拷貝與淺拷貝機制全解析:clone()、序列化與最佳實踐

     編輯:Java 相關知識

核心概念

  • 淺拷貝:基本型別與不可變物件(String)複製值;引用型別僅複製引用,指向同一物件
  • 深拷貝:所有層級物件遞歸複製,完全獨立,互不影響

Object.clone() 機制

四步驟規範

  1. 覆寫 clone() 並宣告 public
  2. 調用 super.clone()
  3. 實作 Cloneable 介面(標記介面,無方法)
  4. 處理 CloneNotSupportedException

protected 修飾原因

Object.clone() 回傳型別無法確定,需由子類覆寫決定具體回傳型別,故設為 protected(包內可見 + 可繼承)。

Cloneable 標記介面作用

JVM 透過 instanceof Cloneable 判斷是否允許克隆,未實作拋出 CloneNotSupportedException。

淺拷貝實作(直接 super.clone())

public class ClassA implements Cloneable {
    private int id;
    private String name;
    private Date date; // 可變物件!

    @Override
    public ClassA clone() throws CloneNotSupportedException {
        return (ClassA) super.clone(); // 淺拷貝:date 共享同一物件
    }
}

修改 clone.date 會影響原物件。

深拷貝實作(手動複製引用欄位)

@Override
public ClassA clone() throws CloneNotSupportedException {
    ClassA cloned = (ClassA) super.clone();
    cloned.date = (Date) date.clone(); // 手動深層複製可變物件
    return cloned;
}

缺點:物件圖複雜時需層層 clone(),代碼繁瑣且易遺漏。

序列化深拷貝(通用、簡潔)

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();
}

前提:物件及所有引用物件必須實作 Serializable。不想序列化的欄位標記 transient。

transient 關鍵字

實作 Serializable 後,transient 欄位會被序列化忽略,適合敏感資料或非序列化物件(如資料庫連線、執行緒)。

選型指南

場景推薦方式理由
簡單物件、少量引用手動深拷貝效能最好、無依賴
複雜物件圖、框架整合序列化深拷貝一行代碼解決、不易漏
資料庫查詢、不需關聯物件淺拷貝效能高、符合語意
含非序列化物件手動深拷貝 + transient序列化會失敗

總結

淺/深拷貝無絕對優劣,視業務場景選擇。序列化雖有效能開銷,但對複雜物件圖是最安全、維護成本最低的方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved