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

Java 深拷貝與淺拷貝完整指南:clone() 陷阱與最佳實踐

     編輯:Java 相關知識

Java 無指針概念,但對象傳遞實為引用傳遞。簡單賦值 (`obj2 = obj1`) 僅複製引用,修改會影響原對象。若需獨立副本,必須正確實現拷貝機制。

引用傳遞 vs 值傳遞演示


public void changeObj(Obj o) { o.str = "changed"; } // 修改原對象
public void changePri(int i) { i = 22; }             // 不影響原變量

基本類型傳值,對象傳引用。這是理解拷貝必要性的前提。

clone() 機制詳解

  1. 實現 Cloneable 標記接口(否則拋 CloneNotSupportedException)。
  2. 重寫 clone() 並調用 super.clone()(native 方法,高效逐位複製)。
  3. 設置 public 訪問權限。

淺拷貝:引用類型共享內存


class CloneB implements Cloneable {
    int aInt;
    UnCloneA unCA; // 引用類型
    // 僅調用 super.clone()
}

結果:基本類型獨立,引用類型指向同一對象。修改 `b2.unCA` 會影響 `b1.unCA`。

深拷貝:遞歸拷貝引用對象


class CloneB implements Cloneable {
    int aInt;
    UnCloneA unCA;

    @Override
    public Object clone() {
        CloneB o = (CloneB) super.clone();
        o.unCA = (UnCloneA) unCA.clone(); // 關鍵:手動拷貝引用字段
        return o;
    }
}

要求所有引用類型字段均實現 Cloneable 並重寫 clone()。

特殊情況處理

類型拷貝策略
String不可變對象,淺拷貝即安全(修改實為新建對象)。
StringBuffer / final 類 / 第三方庫類無法繼承實現 clone(),需在 clone() 中手動 new StringBuffer(old.toString()) 重建。
集合需逐元素深拷貝,或使用序列化/JSON 轉換實現通用深拷貝。

現代替代方案(推薦)

  • 序列化深拷貝:ByteArrayOutputStream + ObjectOutputStream 寫入,再反序列化。通用但需實現 Serializable,性能一般。
  • JSON 轉換:Gson/Jackson 序列化為 JSON 再反序列化。跨平台、可讀、性能尚可,首選方案。
  • MapStruct / 构造器/Builder 模式:編譯期生成拷貝代碼,類型安全、高性能。

避免手寫 clone() 的無限遞歸與維護地獄,拥抱序列化或映射框架,是現代 Java 開發的明智之選。

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