Skip to content

深拷贝和浅拷贝区别

区别

  • 浅拷贝(Shallow Copy)
  • 复制对象时,只复制基本类型字段的值,引用类型字段复制引用地址(指向同一对象)。
  • 深拷贝(Deep Copy)
  • 复制对象时,基本类型和引用类型字段都创建新副本,生成完全独立的对象。

核心点

  • 浅拷贝:修改副本的引用字段会影响原对象。
  • 深拷贝:副本与原对象互不影响。

1. 区别详解

(1) 定义

  • 浅拷贝
  • 复制一层,引用字段仍指向原对象。
  • 深拷贝
  • 递归复制所有层,包含引用字段的完整内容。

(2) 复制内容

  • 浅拷贝
  • 基本类型(如 intdouble):复制值。
  • 引用类型(如 ListObject):复制地址。
  • 深拷贝
  • 基本类型:复制值。
  • 引用类型:递归复制对象内容。

(3) 影响

  • 浅拷贝
  • 修改副本的引用字段,原对象同步变化。
  • 深拷贝
  • 修改副本,原对象不受影响。

示例

class Person implements Cloneable {
    int age; // 基本类型
    List<String> hobbies; // 引用类型

    Person(int age, List<String> hobbies) {
        this.age = age;
        this.hobbies = hobbies;
    }

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

// 测试
List<String> hobbies = new ArrayList<>(Arrays.asList("reading"));
Person p1 = new Person(25, hobbies);

// 浅拷贝
Person p2 = (Person) p1.clone();
p2.age = 30; // 修改基本类型
p2.hobbies.add("gaming"); // 修改引用类型

System.out.println(p1.age);       // 25
System.out.println(p1.hobbies);   // [reading, gaming]
System.out.println(p2.age);       // 30
System.out.println(p2.hobbies);   // [reading, gaming]

// 深拷贝(手动实现)
Person p3 = new Person(p1.age, new ArrayList<>(p1.hobbies));
p3.age = 35;
p3.hobbies.add("swimming");

System.out.println(p1.age);       // 25
System.out.println(p1.hobbies);   // [reading, gaming]
System.out.println(p3.age);       // 35
System.out.println(p3.hobbies);   // [reading, swimming]

2. 实现方式

浅拷贝

  • clone() 方法
  • 默认浅拷贝,需实现 Cloneable
  • 构造器复制
  • 手动赋值字段。
  • 对象赋值
  • Object.assign()(JavaScript 示例,非 Java)。

深拷贝

  • 手动递归复制
  • 复制引用字段时创建新对象。
Person deepCopy() {
    return new Person(this.age, new ArrayList<>(this.hobbies));
}
  • 序列化
  • 通过 Serializable,序列化后反序列化。
public Object deepCopy() throws Exception {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(this);
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bis);
    return ois.readObject();
}
  • 第三方库
  • 如 Gson、Jackson 转 JSON 再还原。

3. 特点对比

特性 浅拷贝 深拷贝
复制深度 一层 所有层
引用字段 复制地址 复制内容
性能 快(少复制) 慢(全复制)
内存 占用少 占用多
独立性 不完全独立 完全独立

4. 延伸与面试角度

  • 适用场景
  • 浅拷贝:简单对象,引用字段无需独立(如配置)。
  • 深拷贝:复杂对象,需隔离(如对象克隆)。
  • 注意事项
  • 浅拷贝:引用修改需谨慎。
  • 深拷贝:循环引用需处理(如序列化)。
  • 实际应用
  • 浅拷贝:ArrayListclone()
  • 深拷贝:对象备份、原型模式。
  • 面试点
  • 问“区别”时,提引用字段影响。
  • 问“实现”时,提序列化。

总结

浅拷贝只复制一层,引用字段共享;深拷贝全复制,独立性强。浅拷贝快但不安全,深拷贝慢但可靠。面试时,可写代码或提场景(如原型模式),展示理解深度。