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

Java Clone 深度解析:從 Cloneable 介面到淺/深複製、序列化替代方案與最佳實務

     編輯:Java 程式設計入門

核心前提:Cloneable 標記介面

所有支援 clone() 的類別必須實作 java.lang.Cloneable(標記介面,無方法)。否則呼叫 clone() 會拋出 CloneNotSupportedException。

Object.clone() 來源碼關鍵點

protected native Object clone() throws CloneNotSupportedException;
// @exception CloneNotSupportedException if the object's class does not support Cloneable
  • protected 可見性 → 子類別或同套件才能直接呼叫。
  • 若需對外公開,**必須覆寫為 public**。

標準實作範本

public class CloneableExample implements Cloneable {
    private String name;
    private int score;

    @Override
    public Object clone() throws CloneNotSupportedException {
        // 1. 呼叫父類別 clone 取得淺複製
        CloneableExample cloned = (CloneableExample) super.clone();

        // 2. 【關鍵】深複製可變參考型別欄位
        // 本例 String、int 為不可變/基本型別,無需處理
        // 若有 List、Date、自訂物件等,必須在此手動新建副本

        // 3. 可選:自訂複製後調整
        // cloned.name = "New Name";
        // cloned.score = 90;

        return cloned;
    }
}

淺複製 vs. 深複製

維度淺複製深複製
基本型別複製值複製值
不可變物件共享參考(安全)共享參考(安全)
可變物件共享參考 ⚠️遞迴新建副本 ✅
實作成本低高(需手動遞迴)

深複製三大實作策略

1. 手動覆寫 clone() 遞迴複製

優點:完全可控、效能最好。缺點:樣板碼多、維護負擔大、易遺漏欄位。

2. 序列化/反序列化(通用深複製)

public static  T deepClone(T obj) {
    try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(bos)) {
        oos.writeObject(obj);
        try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
             ObjectInputStream ois = new ObjectInputStream(bis)) {
            return (T) ois.readObject();
        }
    } catch (Exception e) { throw new RuntimeException(e); }
}

優點:一次處理整個物件圖、無需逐欄位寫碼。缺點:效能較差、需實作 Serializable、transient 欄位會遺失。

3. 第三方函式庫

  • Apache Commons Lang:SerializationUtils.clone(obj)
  • Kryo:高效能序列化框架,支援深複製。
  • MapStruct / ModelMapper:DPO 轉換器,亦可用於複製。

現代替代方案:不可變資料類別 + 建構者模式

Java 14+ record、Lombok @Value、Immutables 框架:

  • 天生不可變 → 不需要複製,直接共享安全。
  • 需「修改」時用 withXxx() 產生新實例(持久化資料結構)。

最佳實務清單

  1. 實作 Cloneable 並覆寫 public Object clone()。
  2. 先呼叫 super.clone(),再手動深複製所有可變參考欄位。
  3. 文件化「哪些欄位為深複製、哪些為共享」。
  4. 考慮以 序列化深複製 或 不可變設計 替代手動 clone。
  5. 單元測試驗證:修改原物件可變欄位不影響複製品,反之亦然。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved