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

Java 每日一題:clone 淺拷貝導致監護人對象共享 Bug 復現與修復

     編輯:Java 綜合教學

Java 每日一題:clone 淺拷貝導致監護人對象共享 Bug 復現與修復

題目代碼

public class Ques1209 {
    public static void main(String[] args) {
        People guardian = new People("張三");
        People son1 = new People("兒子1", guardian);
        People son2 = son1.clone(); // 淺拷貝
        son2.setName("兒子2");
        son1.getGuarder().setName("李四"); // 修改共享對象
        System.out.println(son1.getName() + "的監護人是:" + son1.getGuarder().getName());
        System.out.println(son2.getName() + "的監護人是:" + son2.getGuarder().getName());
    }
}

class People implements Cloneable {
    private String name;
    private People guarder;
    // 構造器、getter/setter 省略
    @Override
    public People clone() {
        try { return (People) super.clone(); }
        catch (Exception e) { throw new RuntimeException(e); }
    }
}

運行結果

兒子1的監護人是:李四
兒子2的監護人是:李四

核心問題

  • super.clone() 執行**淺拷貝**:基本類型複製值,引用類型**複製引用地址**。
  • son1 與 son2 的 guarder 指向**同一個 People 對象**(張三/李四)。
  • 修改任一兒子的監護人名稱,**另一個兒子同步變化**。

內存圖解

son1 ──────► guarder ──────► People("李四")
                ▲
son2 ───────────┘

修復方案:深拷貝

@Override
public People clone() {
    try {
        People p = (People) super.clone();
        // 關鍵:手動拷貝引用類型字段
        if (this.guarder != null) {
            p.guarder = this.guarder.clone(); // 遞歸深拷貝
        }
        return p;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

修復後結果

兒子1的監護人是:李四
兒子2的監護人是:張三

深拷貝三大實現方式對比

最佳實踐建議

  1. 優先不可變對象:guarder 設計為不可變,根除共享風險。
  2. 防御性拷貝:Getter 返回拷貝、Setter 存入拷貝(this.guarder = new People(other.getName()))。
  3. 文檔標註:類註釋聲明「可變/不可變、淺/深拷貝語義」。
  4. 單元測試守護:測試 clone() 後修改原對象不影響副本。

clone() 看似簡單,**淺拷貝是默認陷阱**,深拷貝需顯式編碼。這道題考察的正是對象圖拷貝語義的深度理解。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方式優點缺點適用場景
重寫 clone + 手動拷貝可控、性能好代碼繁瑣、易漏字段字段少、對象圖簡單
序列化反序列化通用、自動深拷貝需實現 Serializable、性能差、不支持 transient通用工具類、對象圖複雜
第三方庫 (Apache Commons Lang / Hutool)一行代碼、處理循環引用引入依賴、反射性能損耗項目已引入工具包