Java 深拷贝与浅拷贝


一、概念总览

1.1 三种拷贝方式对比

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#fdfdfd"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

graph TB
    %% 样式定义
    classDef refStyle fill:#e3f2fd,stroke:#2196f3,stroke-width:2px,color:#0d47a1;
    classDef shallowStyle fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100;
    classDef deepStyle fill:#f1f8e9,stroke:#4caf50,stroke-width:2px,color:#1b5e20;
    classDef titleStyle fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px,color:#333,font-weight:bold;

    MainTitle(["Java 对象拷贝方式总览"])

    subgraph SourceObject ["原始对象 A (Memory Structure)"]
        A_Data["name = '张三'"]
        A_Addr["address"]
        Target[("Address Object: 北京")]
        A_Addr -- "引用指向" --> Target
    end

    subgraph CopyTypes ["三种拷贝机制对比"]
        direction LR

        subgraph RefCopy ["引用拷贝 (Reference Copy)"]
            R1["两个引用指向同一对象"]
            R2["A == B (地址相同)"]
            R3["修改 B 会影响 A"]
        end

        subgraph ShallowCopy ["浅拷贝 (Shallow Copy)"]
            S1["创建新对象 B"]
            S2["基本类型拷贝值"]
            S3["引用类型共享地址"]
        end

        subgraph DeepCopy ["深拷贝 (Deep Copy)"]
            D1["完全独立的新对象"]
            D2["递归拷贝所有层级"]
            D3["修改 B 对 A 无影响"]
        end
    end

    subgraph Comparison ["底层效果直观对比"]
        C1["B ──┐<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─> [同一个对象] <br/>A ──┘"]
        C2["B (新对象) ──> [共享 Address] <br/>A (原对象) ──> [共享 Address]"]
        C3["B (新对象) ──> [新 Address] <br/>A (原对象) ──> [原 Address]"]
    end

    %% 连接逻辑
    MainTitle --> SourceObject
    SourceObject --> CopyTypes

    RefCopy ==> C1
    ShallowCopy ==> C2
    DeepCopy ==> C3

    %% 应用样式
    class RefCopy,R1,R2,R3,C1 refStyle;
    class ShallowCopy,S1,S2,S3,C2 shallowStyle;
    class DeepCopy,D1,D2,D3,C3 deepStyle;
    class MainTitle titleStyle;
    class SourceObject,A_Data,A_Addr,Target titleStyle;

1.2 一句话定义

拷贝类型 定义 修改影响
引用拷贝 复制引用地址,两个引用指向同一对象 完全影响
浅拷贝 创建新对象,但内部引用类型属性共享 部分影响
深拷贝 创建新对象,所有层级都是全新的 互不影响


二、引用拷贝

2.1 概念图解

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

flowchart LR

    %% 样式定义
    classDef stackStyle fill:#e3f2fd,stroke:#2196f3,stroke-width:2px,color:#0d47a1;
    classDef heapStyle fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100;
    classDef codeStyle fill:#f5f5f5,stroke:#9e9e9e,stroke-dasharray: 5 5,color:#333;
    classDef noteStyle fill:#e8f5e9,stroke:#4caf50,stroke-width:1px,color:#1b5e20;

    %% 顶部代码展示
    Code["代码:Person p2 = p1;"]:::codeStyle

    subgraph Memory ["内存布局 (引用拷贝)"]
        direction LR

        subgraph Stack ["栈内存 (Stack)"]
            P1["p1 = 0x100"]:::stackStyle
            P2["p2 = 0x100"]:::stackStyle
        end

        subgraph Heap ["堆内存 (Heap)"]
            Object["<b>Person 对象</b><br/>name = '张三'<br/>age = 20<br/><i>地址: 0x100</i>"]:::heapStyle
        end

        %% 引用指向
        P1 ==> Object
        P2 ==> Object
    end

    %% 特点描述
    Features["<b>特点说明:</b><br/>• 没有创建新对象<br/>• 两个引用指向同一个内存地址<br/>• 修改 p1 会同步反映在 p2 上"]:::noteStyle

    %% 布局辅助
    Code ~~~ Memory
    Memory ~~~ Features

2.2 代码示例

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter 和 Setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

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

/**
 * 引用拷贝测试
 */
public class ReferenceCopyDemo {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 20);

        // ===== 引用拷贝 =====
        Person p2 = p1;  // 只是复制了引用地址

        System.out.println("===== 修改前 =====");
        System.out.println("p1: " + p1);
        System.out.println("p2: " + p2);
        System.out.println("p1 == p2: " + (p1 == p2));  // true

        // 通过 p2 修改
        p2.setAge(25);
        p2.setName("李四");

        System.out.println("\n===== 通过 p2 修改后 =====");
        System.out.println("p1: " + p1);  // p1 也变了!
        System.out.println("p2: " + p2);
    }
}

输出结果:

===== 修改前 =====
p1: Person{name='张三', age=20}
p2: Person{name='张三', age=20}
p1 == p2: true

===== 通过 p2 修改后 =====
p1: Person{name='李四', age=25}
p2: Person{name='李四', age=25}

三、浅拷贝

3.1 概念图解

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

graph LR
    %% 定义样式
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
    classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
    classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;

    subgraph Stack ["栈内存 (Stack)"]
        P1_Ref["p1 = 0x100"]
        P2_Ref["p2 = 0x200"]
    end

    subgraph Heap ["堆内存 (Heap)"]
        subgraph Object1 ["Person 对象 (0x100)"]
            P1_Data["name: '张三'<br/>age: 20<br/>address: 0x300"]
        end

        subgraph Object2 ["Person 对象 (0x200)"]
            P2_Data["name: '张三'<br/>age: 20<br/>address: 0x300"]
        end

        Addr_Obj[("Address 对象 (0x300)<br/>city: '北京'")]
    end

    %% 连线关系
    P1_Ref ==> Object1
    P2_Ref ==> Object2

    P1_Data -. "引用共享" .-> Addr_Obj
    P2_Data -. "引用共享" .-> Addr_Obj

    %% 注释说明
    Note1["<b>浅拷贝特点</b><br/>1. 创建了新对象实例<br/>2. 基本类型值复制<br/>3. 引用类型仅复制地址"]

    %% 应用样式
    class P1_Ref,P2_Ref main;
    class Addr_Obj storage;
    class Note1 term;
    class Object1,Object2 decision;

    %% 布局辅助
    Note1 ~~~ Stack

3.2 实现方式:Cloneable 接口

/**
 * 地址类(引用类型属性)
 */
public class Address {
    private String city;
    private String street;

    public Address(String city, String street) {
        this.city = city;
        this.street = street;
    }

    // Getter 和 Setter
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    public String getStreet() { return street; }
    public void setStreet(String street) { this.street = street; }

    @Override
    public String toString() {
        return "Address{city='" + city + "', street='" + street + "'}";
    }
}

/**
 * Person 类实现浅拷贝
 */
public class Person implements Cloneable {
    private String name;      // String 是不可变对象,特殊处理
    private int age;          // 基本类型
    private Address address;  // 引用类型

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

    /**
     * 浅拷贝实现
     */
    @Override
    public Person clone() {
        try {
            return (Person) super.clone();  // Object.clone() 是浅拷贝
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    // Getter 和 Setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public Address getAddress() { return address; }
    public void setAddress(Address address) { this.address = address; }

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

3.3 浅拷贝测试

public class ShallowCopyDemo {
    public static void main(String[] args) {
        // 创建原始对象
        Address address = new Address("北京", "长安街");
        Person p1 = new Person("张三", 20, address);

        // ===== 浅拷贝 =====
        Person p2 = p1.clone();

        System.out.println("===== 拷贝后初始状态 =====");
        System.out.println("p1: " + p1);
        System.out.println("p2: " + p2);
        System.out.println("p1 == p2: " + (p1 == p2));  // false(不同对象)
        System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress()));  // true(共享)

        // ===== 测试 1:修改基本类型属性 =====
        p2.setAge(25);
        System.out.println("\n===== 修改 p2 的 age 后 =====");
        System.out.println("p1.age: " + p1.getAge());  // 20(不受影响)
        System.out.println("p2.age: " + p2.getAge());  // 25

        // ===== 测试 2:修改引用类型属性的内容 =====
        p2.getAddress().setCity("上海");
        System.out.println("\n===== 修改 p2 的 address.city 后 =====");
        System.out.println("p1.address: " + p1.getAddress());  // 上海(被影响!)
        System.out.println("p2.address: " + p2.getAddress());  // 上海

        // ===== 测试 3:替换整个引用 =====
        p2.setAddress(new Address("广州", "天河路"));
        System.out.println("\n===== 替换 p2 的整个 address 后 =====");
        System.out.println("p1.address: " + p1.getAddress());  // 上海(不受影响)
        System.out.println("p2.address: " + p2.getAddress());  // 广州
    }
}

输出结果:

===== 拷贝后初始状态 =====
p1: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p2: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p1 == p2: false
p1.address == p2.address: true

===== 修改 p2 的 age 后 =====
p1.age: 20
p2.age: 25

===== 修改 p2 的 address.city 后 =====
p1.address: Address{city='上海', street='长安街'}
p2.address: Address{city='上海', street='长安街'}

===== 替换 p2 的整个 address 后 =====
p1.address: Address{city='上海', street='长安街'}
p2.address: Address{city='广州', street='天河路'}

3.4 Object.clone() 源码分析

/**
 * Object 类中的 clone 方法(native 方法)
 */
protected native Object clone() throws CloneNotSupportedException;
%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

flowchart TB
    %% 样式定义
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
    classDef error fill:#ffebee,stroke:#f44336,stroke-width:1.5px,color:#b71c1c;
    classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;

    Start(["开始调用 Object.clone()"]) --> CheckInterface{"是否实现<br/>Cloneable 接口?"}

    %% 异常分支
    CheckInterface -- 否 --> ThrowEx[/"抛出 CloneNotSupportedException"/]
    class ThrowEx error

    %% 正常流程
    CheckInterface == 是 ==> Allocate["创建新对象<br/>(分配内存空间)"]
    class Allocate main

    Allocate ==> FieldCopy[["执行字段复制 (Field Copy)"]]

    subgraph CopyDetail [" 字段复制机制 (浅拷贝) "]
        direction TB
        Primitive["基本类型<br/>(int, double, boolean...)"] -- 直接复制值 --> Value["新旧对象值相同"]
        Reference["引用类型<br/>(对象、数组)"] -- 复制引用地址 --> Address["指向堆中同一个对象"]
    end

    FieldCopy --- CopyDetail

    CopyDetail ==> Return(["返回新对象的引用"])
    class Return term

    %% 节点样式应用
    class CheckInterface decision
    class FieldCopy main
    class Primitive,Reference storage

四、深拷贝

4.1 概念图解

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

flowchart LR
    %% 样式定义
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
    classDef highlight fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100;

    %% 栈内存区域
    subgraph Stack ["栈内存 (Stack)"]
        P1_Ref["p1 = 0x100"]
        P2_Ref["p2 = 0x200"]
    end

    %% 堆内存区域
    subgraph Heap ["堆内存 (Heap)"]
        %% P1 的对象结构
        subgraph P1_Area ["原始对象 P1"]
            P1_Obj["Person 对象 (0x100)<br/>name: '张三'<br/>age: 20"]
            P1_Addr_Ref["address (指向 0x300)"]
        end

        %% P2 的对象结构
        subgraph P2_Area ["克隆对象 P2"]
            P2_Obj["Person 对象 (0x200)<br/>name: '张三'<br/>age: 20"]
            P2_Addr_Ref["address (指向 0x400)"]
        end

        %% Address 对象
        Addr1[("Address 对象 (0x300)<br/>city: '北京'")]
        Addr2[("Address 对象 (0x400)<br/>city: '北京'")]
    end

    %% 逻辑连接
    P1_Ref ==> P1_Obj
    P2_Ref ==> P2_Obj

    P1_Obj --- P1_Addr_Ref
    P1_Addr_Ref --> Addr1

    P2_Obj --- P2_Addr_Ref
    P2_Addr_Ref --> Addr2

    %% 独立性说明
    Status{"完全独立"}
    Addr1 -.-> Status
    Addr2 -.-> Status

    %% 应用样式
    class P1_Ref,P2_Ref main;
    class Addr1,Addr2 storage;
    class Status highlight;

    %% 标注
    Note1["代码:Person p2 = p1.deepClone();"]
    Note1 ~~~ Stack

4.2 实现方式一:手动递归拷贝

/**
 * Address 类 - 支持深拷贝
 */
public class Address implements Cloneable {
    private String city;
    private String street;

    public Address(String city, String street) {
        this.city = city;
        this.street = street;
    }

    /**
     * Address 自己的 clone 方法
     */
    @Override
    public Address clone() {
        try {
            return (Address) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    // Getter/Setter/toString 省略
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    public String getStreet() { return street; }
    public void setStreet(String street) { this.street = street; }

    @Override
    public String toString() {
        return "Address{city='" + city + "', street='" + street + "'}";
    }
}

/**
 * Person 类 - 实现深拷贝
 */
public class Person implements Cloneable {
    private String name;
    private int age;
    private Address address;

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

    /**
     * 深拷贝实现:递归调用内部对象的 clone
     */
    @Override
    public Person clone() {
        try {
            Person cloned = (Person) super.clone();
            // 关键:对引用类型属性也进行拷贝
            if (this.address != null) {
                cloned.address = this.address.clone();
            }
            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    // Getter/Setter 省略
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public Address getAddress() { return address; }
    public void setAddress(Address address) { this.address = address; }

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

4.3 深拷贝测试

public class DeepCopyDemo {
    public static void main(String[] args) {
        // 创建原始对象
        Address address = new Address("北京", "长安街");
        Person p1 = new Person("张三", 20, address);

        // ===== 深拷贝 =====
        Person p2 = p1.clone();

        System.out.println("===== 拷贝后初始状态 =====");
        System.out.println("p1: " + p1);
        System.out.println("p2: " + p2);
        System.out.println("p1 == p2: " + (p1 == p2));
        System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress()));

        // ===== 修改 p2 的 address.city =====
        p2.getAddress().setCity("上海");

        System.out.println("\n===== 修改 p2 的 address.city 后 =====");
        System.out.println("p1.address: " + p1.getAddress());  // 北京(不受影响!)
        System.out.println("p2.address: " + p2.getAddress());  // 上海
    }
}

输出结果

===== 拷贝后初始状态 =====
p1: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p2: Person{name='张三', age=20, address=Address{city='北京', street='长安街'}}
p1 == p2: false
p1.address == p2.address: false

===== 修改 p2 的 address.city 后 =====
p1.address: Address{city='北京', street='长安街'}
p2.address: Address{city='上海', street='长安街'}

4.4 实现方式二:序列化方式(推荐)

import java.io.*;

/**
 * 使用序列化实现深拷贝
 */
public class DeepCopyUtil {

    /**
     * 通过序列化实现深拷贝
     * 要求:对象及其所有属性都必须实现 Serializable 接口
     */
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T deepCopy(T object) {
        try {
            // 1. 将对象写入字节流
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            oos.close();

            // 2. 从字节流读取对象
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            T copy = (T) ois.readObject();
            ois.close();

            return copy;
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException("深拷贝失败", e);
        }
    }
}

/**
 * 实体类需要实现 Serializable
 */
public class Address implements Serializable {
    private static final long serialVersionUID = 1L;
    private String city;
    private String street;
    // ... 其他代码
}

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private Address address;
    // ... 其他代码
}

/**
 * 使用示例
 */
public class SerializationDeepCopyDemo {
    public static void main(String[] args) {
        Address address = new Address("北京", "长安街");
        Person p1 = new Person("张三", 20, address);

        // 深拷贝
        Person p2 = DeepCopyUtil.deepCopy(p1);

        System.out.println("p1.address == p2.address: " + (p1.getAddress() == p2.getAddress()));
        // false(完全独立)

        p2.getAddress().setCity("上海");
        System.out.println("p1.address.city: " + p1.getAddress().getCity());  // 北京
        System.out.println("p2.address.city: " + p2.getAddress().getCity());  // 上海
    }
}

4.5 实现方式三:JSON 序列化(第三方库)

import com.google.gson.Gson;
// 或者
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 使用 Gson 实现深拷贝
 */
public class JsonDeepCopy {
    private static final Gson gson = new Gson();

    public static <T> T deepCopy(T object, Class<T> clazz) {
        String json = gson.toJson(object);
        return gson.fromJson(json, clazz);
    }
}

/**
 * 使用 Jackson 实现深拷贝
 */
public class JacksonDeepCopy {
    private static final ObjectMapper mapper = new ObjectMapper();

    public static <T> T deepCopy(T object, Class<T> clazz) {
        try {
            String json = mapper.writeValueAsString(object);
            return mapper.readValue(json, clazz);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

// 使用示例
Person p2 = JsonDeepCopy.deepCopy(p1, Person.class);

4.6 深拷贝实现方式对比

实现方式 优点 缺点 适用场景
手动递归 性能最好,可定制 代码量大,易遗漏 简单对象
序列化 通用,自动处理嵌套 性能较差,需实现 Serializable 复杂对象
JSON 简单,无需特殊接口 性能一般,需引入依赖 与前端交互的对象
拷贝构造器 直观,可控 每个类都要写 明确需要拷贝的类


五、三种拷贝对比

5.1 完整对比图

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

flowchart TB

    %% 样式定义
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
    classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;
    classDef note fill:#fafafa,stroke:#9e9e9e,stroke-dasharray: 5 5;

    subgraph RefCopy ["引用拷贝 (Reference Copy)"]
        direction LR
        R_p1["p1 (引用)"]
        R_p2["p2 (引用)"]
        R_Obj1[["Person 对象"]]
        R_Addr1[("Address 对象")]

        R_p1 --> R_Obj1
        R_p2 --> R_Obj1
        R_Obj1 -- "address 属性" --> R_Addr1

        R_Note["✗ 没有创建新对象<br/>✗ 修改任何属性都互相影响"]
        class R_Note note
    end

    subgraph ShallowCopy ["浅拷贝 (Shallow Copy)"]
        direction LR
        S_p1["p1 (引用)"]
        S_p2["p2 (引用)"]
        S_Obj1[["Person 对象 (原)"]]
        S_Obj2[["Person 对象 (新)"]]
        S_Addr1[("Address 对象 (共享)")]

        S_p1 --> S_Obj1
        S_p2 --> S_Obj2
        S_Obj1 -- "address" --> S_Addr1
        S_Obj2 -- "address" --> S_Addr1

        S_Note["✓ 创建了新 Person 对象<br/>✓ 基本类型独立<br/>✗ 引用类型属性共享"]
        class S_Note note
    end

    subgraph DeepCopy ["深拷贝 (Deep Copy)"]
        direction LR
        D_p1["p1 (引用)"]
        D_p2["p2 (引用)"]
        D_Obj1[["Person 对象 (原)"]]
        D_Obj2[["Person 对象 (新)"]]
        D_Addr1[("Address 对象 (原)")]
        D_Addr2[("Address 对象 (新)")]

        D_p1 --> D_Obj1
        D_p2 --> D_Obj2
        D_Obj1 -- "address" --> D_Addr1
        D_Obj2 -- "address" --> D_Addr2

        D_Note["✓ 所有属性完全独立<br/>✓ 递归复制引用对象<br/>✓ 完全互不影响"]
        class D_Note note
    end

    %% 应用样式
    class R_p1,R_p2,S_p1,S_p2,D_p1,D_p2 main
    class R_Obj1,S_Obj1,S_Obj2,D_Obj1,D_Obj2 decision
    class R_Addr1,S_Addr1,D_Addr1,D_Addr2 storage

5.2 修改影响对比表

操作 引用拷贝 浅拷贝 深拷贝
修改 p2.age(基本类型) p1 受影响 p1 不受影响 p1 不受影响
修改 p2.name(String,不可变) p1 受影响 p1 不受影响* p1 不受影响
修改 p2.address.city p1 受影响 p1 受影响 p1 不受影响
替换 p2.address = new Address() p1 受影响 p1 不受影响 p1 不受影响

*注:String 是不可变对象,重新赋值会创建新对象,所以表现得像深拷贝。


5.3 综合测试代码

public class CopyComparisonDemo {
    public static void main(String[] args) {
        System.out.println("========== 1. 引用拷贝 ==========");
        testReferenceCopy();

        System.out.println("\n========== 2. 浅拷贝 ==========");
        testShallowCopy();

        System.out.println("\n========== 3. 深拷贝 ==========");
        testDeepCopy();
    }

    static void testReferenceCopy() {
        Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
        Person p2 = p1;  // 引用拷贝

        p2.getAddress().setCity("上海");

        System.out.println("修改 p2.address.city 后:");
        System.out.println("p1.address.city = " + p1.getAddress().getCity());  // 上海
        System.out.println("p2.address.city = " + p2.getAddress().getCity());  // 上海
        System.out.println("结论: p1 受影响");
    }

    static void testShallowCopy() {
        Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
        Person p2 = p1.shallowClone();  // 浅拷贝

        p2.getAddress().setCity("上海");

        System.out.println("修改 p2.address.city 后:");
        System.out.println("p1.address.city = " + p1.getAddress().getCity());  // 上海
        System.out.println("p2.address.city = " + p2.getAddress().getCity());  // 上海
        System.out.println("结论: p1 受影响(共享内部对象)");
    }

    static void testDeepCopy() {
        Person p1 = new Person("张三", 20, new Address("北京", "长安街"));
        Person p2 = p1.deepClone();  // 深拷贝

        p2.getAddress().setCity("上海");

        System.out.println("修改 p2.address.city 后:");
        System.out.println("p1.address.city = " + p1.getAddress().getCity());  // 北京
        System.out.println("p2.address.city = " + p2.getAddress().getCity());  // 上海
        System.out.println("结论: p1 不受影响(完全独立)");
    }
}

六、复杂场景:多层嵌套

6.1 多层嵌套对象

/**
 * 公司类(多层嵌套示例)
 */
public class Company implements Serializable, Cloneable {
    private String name;
    private Address headquarters;        // 第1层嵌套
    private List<Department> departments; // 集合嵌套

    // 深拷贝(手动实现)
    @Override
    public Company clone() {
        try {
            Company cloned = (Company) super.clone();

            // 拷贝 Address
            if (this.headquarters != null) {
                cloned.headquarters = this.headquarters.clone();
            }

            // 拷贝 List<Department>
            if (this.departments != null) {
                cloned.departments = new ArrayList<>();
                for (Department dept : this.departments) {
                    cloned.departments.add(dept.clone());  // 每个元素都要 clone
                }
            }

            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

/**
 * 部门类
 */
public class Department implements Serializable, Cloneable {
    private String name;
    private List<Employee> employees;  // 第2层嵌套

    @Override
    public Department clone() {
        try {
            Department cloned = (Department) super.clone();
            if (this.employees != null) {
                cloned.employees = new ArrayList<>();
                for (Employee emp : this.employees) {
                    cloned.employees.add(emp.clone());
                }
            }
            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

6.2 多层嵌套图示

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

flowchart TB

    subgraph ShallowCopy ["浅拷贝 (Shallow Copy) - 仅复制顶层"]
        direction LR
        S_Orig["原对象 Company"]
        S_Addr["Address 对象"]
        S_List["List 集合"]
        S_Dept["Department 对象"]
        S_Emp["Employee 对象"]

        S_New["新对象 Company"]

        S_Orig --> S_Addr
        S_Orig --> S_List
        S_List --> S_Dept
        S_Dept --> S_Emp

        S_New == "引用相同地址" ==> S_Addr
        S_New == "引用相同地址" ==> S_List
    end

    subgraph DeepCopy ["深拷贝 (Deep Copy) - 递归复制所有层级"]
        direction TB

        subgraph OriginalTree ["原始对象树"]
            direction LR
            O_Comp["Company"] --> O_Addr["Address"]
            O_Addr --> O_List["List"]
            O_List --> O_Dept["Department"]
            O_Dept --> O_Emp["Employee"]
        end

        subgraph NewTree ["全新副本树"]
            direction LR
            N_Comp["Company"] --> N_Addr["Address"]
            N_Addr --> N_List["List"]
            N_List --> N_Dept["Department"]
            N_Dept --> N_Emp["Employee"]
        end

        O_Comp -. "独立副本" .-> N_Comp
        O_Addr -. "独立副本" .-> N_Addr
        O_List -. "独立副本" .-> N_List
        O_Dept -. "独立副本" .-> N_Dept
        O_Emp -. "独立副本" .-> N_Emp
    end

    subgraph Tips ["💡 最佳实践"]
        T1["复杂对象推荐使用序列化/反序列化 (JSON/Protobuf)"]
        T2["手动实现需注意循环引用问题"]
    end

    %% 样式定义
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
    classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;

    class S_New,N_Comp,N_Addr,N_List,N_Dept,N_Emp main;
    class S_Orig,O_Comp,O_Addr,O_List,O_Dept,O_Emp storage;
    class T1,T2 decision;

七、特殊情况处理

7.1 不可变对象

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

flowchart TB

    subgraph Core ["不可变对象核心逻辑"]
        direction TB
        ObjType(["不可变对象 (Immutable Objects)"])
        Examples["String, Integer, LocalDate"]

        Features{{"核心特点"}}
        F1["创建后状态不可改变"]
        F2["修改操作 = 返回新对象"]

        Strategy{{"拷贝处理策略"}}
        S1["直接引用共享 (Shallow Share)"]
        S2["无需深拷贝 (Deep Copy Not Needed)"]
    end

    subgraph Example ["内存变化示例: String name = '张三'"]
        direction LR
        State1["栈变量: name"] -- "初始指向" --> Val1[("堆内存: '张三'")]

        Update["执行: name = '李四'"]

        State1 == "重定向" ==> Val2[("堆内存: '李四'")]
        Val1 -. "原对象保持不变" .-> Val1
    end

    %% 节点连接
    ObjType --- Examples
    Examples --> Features
    Features --> F1
    Features --> F2

    F1 & F2 --> Strategy
    Strategy --> S1
    Strategy --> S2

    S1 ==> Example

    %% 样式定义
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
    classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;

    class ObjType,Examples main;
    class Features,Strategy decision;
    class F1,F2,S1,S2 term;
    class Val1,Val2 storage;

7.2 数组的拷贝

public class ArrayCopyDemo {
    public static void main(String[] args) {
        // ===== 一维基本类型数组 =====
        int[] arr1 = {1, 2, 3};
        int[] arr2 = arr1.clone();  // 深拷贝
        arr2[0] = 100;
        System.out.println(arr1[0]);  // 1(不受影响)

        // ===== 一维引用类型数组 =====
        Person[] persons1 = {new Person("张三", 20, null)};
        Person[] persons2 = persons1.clone();  // 浅拷贝!
        persons2[0].setName("李四");
        System.out.println(persons1[0].getName());  // 李四(受影响!)

        // ===== 二维数组 =====
        int[][] matrix1 = {{1, 2}, {3, 4}};
        int[][] matrix2 = matrix1.clone();  // 浅拷贝!
        matrix2[0][0] = 100;
        System.out.println(matrix1[0][0]);  // 100(受影响!)

        // ===== 二维数组深拷贝 =====
        int[][] matrix3 = new int[matrix1.length][];
        for (int i = 0; i < matrix1.length; i++) {
            matrix3[i] = matrix1[i].clone();  // 每行单独 clone
        }
    }
}

数组拷贝总结

数组类型 clone() / Arrays.copyOf() 效果
一维基本类型 深拷贝 ✅ 独立
一维引用类型 浅拷贝 ⚠️ 元素共享
二维数组 浅拷贝 ⚠️ 行数组共享

八、最佳实践与总结

8.1 选择建议

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

graph TB
    %% 样式定义
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
    classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
    classDef highlight fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;

    subgraph SelectionGuide ["对象拷贝选择建议"]
        direction TB

        Start(["开始判断"]) --> Q1{"需要拷贝对象吗?"}

        Q1 -- "只读使用" --> Result1["引用拷贝<br/>(无需物理拷贝)"]
        Q1 -- "需要修改" --> Q2{"对象包含引用属性?"}

        Q2 -- "没有" --> Result2["浅拷贝<br/>(Shallow Copy)"]
        Q2 -- "有" --> Q3{"内部引用也需要<br/>独立修改吗?"}

        Q3 -- "否" --> Result3["浅拷贝"]
        Q3 -- "是" --> Result4["深拷贝<br/>(Deep Copy)"]
    end

    %% 节点分类应用
    class Start main;
    class Q1,Q2,Q3 decision;
    class Result1,Result2,Result3 term;
    class Result4 highlight;

    %% 核心路径加粗
    Q2 == "有" ==> Q3
    Q3 == "是" ==> Result4

    %% 补充说明样式
    style SelectionGuide fill:#fcfcfc,stroke:#d1d1d1,stroke-dasharray: 5 5;

8.2 实现方式选择

场景 推荐方式 原因
简单对象,无嵌套 手动 clone 性能最好
复杂对象,多层嵌套 序列化 自动处理所有层级
需要与前端交互 JSON 一举两得
防御性拷贝 拷贝构造器 代码直观
集合拷贝 Stream + 深拷贝 灵活控制

8.3 防御性拷贝

/**
 * 防御性拷贝:保护内部状态不被外部修改
 */
public class ImmutablePerson {
    private final String name;
    private final Date birthDate;  // Date 是可变的!

    public ImmutablePerson(String name, Date birthDate) {
        this.name = name;
        // 防御性拷贝:复制传入的参数
        this.birthDate = new Date(birthDate.getTime());
    }

    public Date getBirthDate() {
        // 防御性拷贝:返回副本而非原对象
        return new Date(birthDate.getTime());
    }
}

8.4 速查表

对比项 引用拷贝 浅拷贝 深拷贝
新对象
基本类型独立
引用类型独立
实现难度 简单 复杂
性能 最快 较慢

8.5 记忆口诀

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#f5f5f5"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true, "useMaxWidth": true }
}}%%

flowchart TB

    %% 核心分类
    Root(["Java/JS 对象拷贝记忆口诀"])

    subgraph RefGroup ["引用拷贝 (Reference Copy)"]
        direction TB
        R1["复制地址,同一对象"]
        R2[["两个名字,一个人"]]
    end

    subgraph ShallowGroup ["浅拷贝 (Shallow Copy)"]
        direction TB
        S1["新皮旧馅,表面功夫"]
        S2["房子是新的,家具是共享的"]
        S3["基本类型复制值,引用类型复制地址"]
    end

    subgraph DeepGroup ["深拷贝 (Deep Copy)"]
        direction TB
        D1["彻底独立,完全分家"]
        D2["房子是新的,家具也全是新的"]
        D3["递归复制,层层独立"]
    end

    subgraph StrategyGroup ["选择口诀 (Strategy)"]
        direction LR
        ST1["只读引用,修改要拷贝"]
        ST2["简单浅拷贝,嵌套深拷贝"]
        ST3["序列化最省心,手动写最性能"]
    end

    %% 连接关系
    Root ==> RefGroup
    Root ==> ShallowGroup
    Root ==> DeepGroup

    RefGroup ~~~ StrategyGroup
    ShallowGroup ==> StrategyGroup
    DeepGroup ==> StrategyGroup

    %% 样式定义
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
    classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;

    class Root main;
    class R1,R2 main;
    class S1,S2,S3 decision;
    class D1,D2,D3 term;
    class ST1,ST2,ST3 storage;

8.6 核心要点图

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#e3f2fd",
    "primaryTextColor": "#0d47a1",
    "primaryBorderColor": "#2196f3",
    "lineColor": "#546e7a",
    "fontSize": "14px",
    "tertiaryColor": "#fdfdfd"
  },
  "flowchart": { "curve": "basis", "htmlLabels": true }
}}%%

graph TB

    %% 核心分类
    subgraph Core ["1. 本质区别 (Copy Types)"]
        Type1["<b>引用拷贝</b><br/>仅复制指针,指向同一内存地址"]
        Type2["<b>浅拷贝</b><br/>创建新对象,但内部引用仍共享"]
        Type3["<b>深拷贝</b><br/>递归复制,完全独立的副本"]
    end

    %% 实现路径
    subgraph Implementation ["2. 实现方式 (Implementation)"]
        direction LR
        Method1[["Object.clone() 默认方式"]]

        subgraph DeepMethods ["深拷贝具体手段"]
            M2["手动递归 Clone"]
            M3["序列化 / 反序列化"]
            M4["JSON 转换"]
            M5["拷贝构造器"]
        end
    end

    %% 注意事项
    subgraph Precautions ["3. 开发注意事项 (Best Practices)"]
        Note1("必须实现 Cloneable 接口")
        Note2("String 等不可变对象无需深拷贝")
        Note3("数组 clone 对引用元素仍是浅拷贝")
        Note4("复杂对象推荐序列化方式")
    end

    %% 逻辑连接
    Type2 -.-> Method1
    Type3 -.-> DeepMethods
    Method1 ==> Note1
    DeepMethods ==> Note4

    %% 样式定义
    classDef main fill:#e3f2fd,stroke:#2196f3,stroke-width:1.5px,color:#0d47a1;
    classDef decision fill:#fff3e0,stroke:#ff9800,stroke-width:1.5px,color:#e65100;
    classDef term fill:#e8f5e9,stroke:#4caf50,stroke-width:1.5px,color:#1b5e20;
    classDef storage fill:#f3e5f5,stroke:#9c27b0,stroke-width:1.5px,color:#4a148c;

    class Type1,Type2,Type3 main;
    class Method1,M2,M3,M4,M5 decision;
    class Note1,Note2,Note3,Note4 term;