跳转至

深拷贝和浅拷贝区别

一、定义

浅拷贝(Shallow Copy)

只复制对象本身和基本类型字段,引用类型字段只复制引用,不复制引用指向的对象。

深拷贝(Deep Copy)

不仅复制对象本身,还递归复制所有引用类型字段指向的对象。

二、图示

原对象 A:
  name: "Tom"
  address: 对象 B (city="北京")

浅拷贝 A':
  name: "Tom"
  address: 同一个对象 B       ← 引用一样

深拷贝 A':
  name: "Tom"
  address: 新对象 B' (city="北京")  ← 复制一份

三、代码示例

class Address {
    String city;
}

class Person implements Cloneable {
    String name;
    Address address;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();   // 浅拷贝
    }
}

浅拷贝

Person p1 = new Person("Tom", new Address("北京"));
Person p2 = (Person) p1.clone();
p2.address.city = "上海";
System.out.println(p1.address.city);   // 上海!p1 也被改了

深拷贝

@Override
protected Object clone() throws CloneNotSupportedException {
    Person p = (Person) super.clone();
    p.address = new Address(this.address.city);   // 复制引用对象
    return p;
}

四、实现方式

1. 重写 clone()

手动 new 每个引用对象。

2. 序列化

实现 Serializable,把对象写出去再读回来,天然深拷贝:

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
ObjectInputStream ois = new ObjectInputStream(
    new ByteArrayInputStream(bos.toByteArray()));
return ois.readObject();

3. JSON 序列化

Pojo copy = JSON.parseJSONString(JSON.toJSONString(obj), Pojo.class);

简单但要注意循环引用。

五、选择

  • 对象简单、引用少:浅拷贝。
  • 有引用类型且需要独立:深拷贝。
  • 用不可变对象:从根本上避免拷贝问题。

clone() 的坑

  • Cloneable 是标记接口,不重写 clone()super.clone() 会抛异常。
  • 数组实现了 Cloneable,但元素引用仍是浅拷贝。
  • Effective Java 建议:用拷贝构造器或工厂,不要用 clone()。