Java 中的**深拷贝(Deep Copy)浅拷贝(Shallow Copy)**是对象复制时两个非常重要的概念,尤其在涉及引用类型属性时,它们的行为差异会直接影响程序的逻辑和数据安全。


🔹 一、基本概念

概念定义
浅拷贝创建一个新对象,但对象中的字段 引用原始对象中的字段值(如果是引用类型,共享同一块内存)。
深拷贝创建一个新对象,并且对象中的 引用类型字段也会被拷贝成新的对象,彼此互不影响。

🔹 二、图示理解

假设有类 Person 包含一个 Address 成员:

Person p1 ──► name: "Tom"
            address ──► city: "Shanghai"

浅拷贝后:

Person p2 ──► name: "Tom"
            address ──► city: "Shanghai"   // 和 p1.address 指向同一个对象

深拷贝后:

Person p2 ──► name: "Tom"
            address ──► city: "Shanghai"   // 新建了一个 Address 对象,内容一样,但引用不同

🔹 三、示例代码

✅ 1. 浅拷贝:使用 clone() 方法

class Address {
    String city;

    Address(String city) {
        this.city = city;
    }
}

class Person implements Cloneable {
    String name;
    Address address;

    Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

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

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address addr = new Address("Shanghai");
        Person p1 = new Person("Tom", addr);
        Person p2 = (Person) p1.clone();

        p2.address.city = "Beijing";  // 修改 p2 的地址

        System.out.println(p1.address.city); // 输出 "Beijing",p1 被影响了
    }
}

✅ 2. 深拷贝:手动实现(逐个 clone)

class Address implements Cloneable {
    String city;

    Address(String city) {
        this.city = city;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return new Address(this.city); // 克隆新对象
    }
}

class Person implements Cloneable {
    String name;
    Address address;

    Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person cloned = (Person) super.clone();
        cloned.address = (Address) this.address.clone();  // 深拷贝
        return cloned;
    }
}

🔹 四、其他深拷贝实现方式

✅ 1. 使用序列化(适用于对象结构复杂的情况)

import java.io.*;

public class DeepClone {
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T copy(T obj) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(obj);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);

        return (T) ois.readObject();
    }
}

缺点:类必须实现 Serializable 接口,性能较低,但优点是通用、结构复杂也能处理。


✅ 2. 使用第三方库

  • Apache Commons Lang:Person copied = SerializationUtils.clone(original);
  • Gson 或 JacksonPerson copied = new Gson().fromJson(new Gson().toJson(original), Person.class);

🔹 五、浅拷贝与深拷贝对比总结

比较项浅拷贝深拷贝
是否新建对象是(主对象)是(主对象 + 所有引用对象)
引用类型字段拷贝引用地址(共享同一个对象)拷贝为新对象(内容一样,地址不同)
影响范围修改引用对象会影响原对象完全独立
实现复杂度简单(clone() 或复制构造)相对复杂(手动逐层复制)
适用场景数据变化不敏感;无需隔离数据隔离要求高

✅ 结语

  • 浅拷贝适合结构简单、对数据引用没影响的场景。
  • 深拷贝适合结构复杂或引用对象多、数据相互隔离要求高的业务。

好的,以下是一个 完整 Java 示例,展示了:

  • 如何实现浅拷贝
  • 如何实现深拷贝
  • 两者行为的区别(运行结果可以清楚看出)

✅ 1. 完整 Java 示例代码

import java.io.*;

// 地址类:实现深拷贝需要实现 Cloneable 接口
class Address implements Cloneable, Serializable {
    String city;

    Address(String city) {
        this.city = city;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return new Address(this.city); // 深拷贝用
    }

    @Override
    public String toString() {
        return city;
    }
}

// 人类:包含引用类型 Address
class Person implements Cloneable, Serializable {
    String name;
    Address address;

    Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    // 浅拷贝
    protected Person shallowClone() throws CloneNotSupportedException {
        return (Person) super.clone(); // Address 仍是引用同一个对象
    }

    // 深拷贝:手动克隆每一层
    protected Person deepClone() throws CloneNotSupportedException {
        Person cloned = (Person) super.clone();
        cloned.address = (Address) this.address.clone();
        return cloned;
    }

    // 深拷贝:序列化方式
    protected Person deepCloneBySerialization() throws IOException, ClassNotFoundException {
        // 写入流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);

        // 读取流
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return (Person) ois.readObject();
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', address=" + address + "}";
    }
}

// 测试类
public class CopyDemo {
    public static void main(String[] args) throws Exception {
        Address address = new Address("Shanghai");
        Person p1 = new Person("Tom", address);

        System.out.println("原始对象:     " + p1);

        // 浅拷贝
        Person shallow = p1.shallowClone();
        shallow.address.city = "Beijing";

        System.out.println("\n== 浅拷贝后修改 shallow.address.city = 'Beijing'");
        System.out.println("原始对象:     " + p1);        // 被影响
        System.out.println("浅拷贝对象:   " + shallow);    // 也改了

        // 深拷贝
        Person deep = p1.deepClone();
        deep.address.city = "Guangzhou";

        System.out.println("\n== 深拷贝后修改 deep.address.city = 'Guangzhou'");
        System.out.println("原始对象:     " + p1);        // 不被影响
        System.out.println("深拷贝对象:   " + deep);

        // 深拷贝(序列化)
        Person deep2 = p1.deepCloneBySerialization();
        deep2.address.city = "Shenzhen";

        System.out.println("\n== 序列化深拷贝后修改 deep2.address.city = 'Shenzhen'");
        System.out.println("原始对象:     " + p1);        // 不被影响
        System.out.println("序列化深拷贝: " + deep2);
    }
}

✅ 2. 运行输出示例

原始对象:     Person{name='Tom', address=Shanghai}

== 浅拷贝后修改 shallow.address.city = 'Beijing'
原始对象:     Person{name='Tom', address=Beijing}
浅拷贝对象:   Person{name='Tom', address=Beijing}

== 深拷贝后修改 deep.address.city = 'Guangzhou'
原始对象:     Person{name='Tom', address=Beijing}
深拷贝对象:   Person{name='Tom', address=Guangzhou}

== 序列化深拷贝后修改 deep2.address.city = 'Shenzhen'
原始对象:     Person{name='Tom', address=Beijing}
序列化深拷贝: Person{name='Tom', address=Shenzhen}

🔚 总结重点

方法Address 是否独立?实现难度说明
shallowClone()❌ 否,共享引用简单快速但易出问题
deepClone()✅ 是中等推荐,控制明确
deepCloneBySerialization()✅ 是较高适合复杂结构、但效率低