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

Java Object.clone() 深度解析:淺拷貝 vs 深拷貝實戰指南

     編輯:Java 綜合教學

Java Object.clone() 深度解析:淺拷貝 vs 深拷貝實戰指南

Object.clone() 是 Java 中創建對象副本的核心機制,但其行為細節(淺拷貝)、拋出的異常、Cloneable 接口的標記作用,常讓開發者踩坑。本文從源碼層面剖析,並通過完整代碼示例演示淺/深拷貝的正確實現姿勢。

一、clone() 源碼核心特徵

protected native Object clone() throws CloneNotSupportedException;
  • native 關鍵字:底層由 C/C++ 實現,直接操作內存,執行效率極高,繞過 Java 層面的對象創建流程。
  • protected 修飾:子類覆寫時通常改為 public,以便外部調用。
  • 拋出 CloneNotSupportedException:類必須實現 Cloneable 標記接口,否則調用直接拋出異常。注意:Cloneable 內部無任何方法,僅作運行時標記。

二、為什麼需要 clone()?賦值 (=) 的陷阱

Java 中對象變量存儲的是引用(內存地址)。直接賦值 Person p2 = p1; 只是複製引用,兩個變量指向同一堆內存對象,修改任一變量可見的屬性都會影響另一個。

賦值引用示意圖

使用 clone() 可在堆內存中分配新空間,複製字段值,實現真正的對象獨立:

clone 複製示意圖

三、淺拷貝 vs 深拷貝:關鍵區別

1. 淺拷貝 —— 僅複製對象本身及基本類型/引用地址

@Override
public ShallowClone clone() {
    try {
        return (ShallowClone) super.clone(); // 僅調用 Object.clone()
    } catch (CloneNotSupportedException e) {
        throw new AssertionError(); // 不會發生,因實現了 Cloneable
    }
}

運行結果證明:c1.person == c2.person(同一引用地址)。修改 c2.person.name 會影響 c1.person。

2. 深拷貝 —— 遞歸複製引用類型字段

@Override
public DeepClone clone() {
    try {
        DeepClone c = (DeepClone) super.clone();
        c.person = person.clone(); // 關鍵:手動複製引用字段
        return c;
    } catch (CloneNotSupportedException e) {
        throw new AssertionError();
    }
}

運行結果:c1.person != c2.person,內存地址不同,修改互不影響。

四、工程落地建議

  1. 優先考慮拷貝構造函數或工廠方法(如 new Person(person)),避開 Cloneable 的繁瑣協議。
  2. 必須用 clone() 時:實現 Cloneable、覆寫為 public、深拷貝所有可變引用字段、文檔說明拷貝策略。
  3. 集合類深拷貝可用 new ArrayList<>(list) 或流式 list.stream().map(Item::clone).collect(toList())。
  4. 不可變對象(如 String、包裝類、LocalDate)無需深拷貝,直接共享引用安全。

總結

clone() 機制強大但易誤用。理解「淺拷貝只複製引用,深拷貝遞歸複製對象圖」是核心。現代開發中,拷貝構造函數/建造者模式/序列化反序列化 往往是更清晰、類型安全的替代方案。

  1. 上一篇文章:
  2. 下一篇文章:
計算機程序思維邏輯 (58):字符流與字節流的本質區別、編碼陷阱與 Java IO 體系全景 Java 核心類庫線程安全與非安全類對照表 JavaWeb 入門基石:HTML 常用標簽、屬性與表單完整速查手冊 Java 加密算法大全:JCA 提供者架構、標準算法名稱與程式碼查詢實戰 Spring MVC 啟動流程深度解析:從 web.xml 到 DispatcherServlet 工作原理 MongoDB 分片集群架構與部署實戰:從原理到生產級配置 JS 載入時機陷阱:為什麼