深拷贝和浅拷贝

在 Java 中,深拷贝(Deep Copy)浅拷贝(Shallow Copy) 是两种常见的对象复制方式。它们的主要区别在于是否复制对象的引用类型字段。

1. 浅拷贝

定义

浅拷贝只复制对象本身,而不复制对象内部的引用类型字段。也就是说,浅拷贝后,原对象和新对象共享引用类型的字段

实现方式

  • 使用 clone() 方法
    • 实现 Cloneable 接口。
    • 重写 clone() 方法。

示例代码

class Person implements Cloneable {
    String name;
    Address address; // 引用类型

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

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

class Address {
    String city;

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

public class ShallowCopyExample {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address address = new Address("New York");
        Person person1 = new Person("Alice", address);

        // 浅拷贝
        Person person2 = (Person) person1.clone();

        // 修改 person2 的引用字段
        person2.address.city = "Los Angeles";

        System.out.println(person1.address.city); // 输出 Los Angeles
        System.out.println(person2.address.city); // 输出 Los Angeles
    }
}

结果分析

  • person1person2 共享同一个 Address 对象。
  • 修改 person2.address.city 后,person1.address.city 也发生了变化。

2. 深拷贝

定义

深拷贝不仅复制对象本身,还递归地复制对象内部的所有引用类型字段。也就是说,深拷贝后,原对象和新对象完全独立

实现方式

  • 手动实现深拷贝
    • 遍历对象的所有字段,并逐一复制。
  • 使用序列化
    • 将对象序列化为字节流,再反序列化为新对象。

方法 1:手动实现深拷贝

class Person implements Cloneable {
    String name;
    Address address;

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 深拷贝
        Person cloned = (Person) super.clone();
        cloned.address = new Address(this.address.city); // 复制引用字段
        return cloned;
    }
}

class Address {
    String city;

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

public class DeepCopyExample {
    public static void main(String[] args) throws CloneNotSupportedException {
        Address address = new Address("New York");
        Person person1 = new Person("Alice", address);

        // 深拷贝
        Person person2 = (Person) person1.clone();

        // 修改 person2 的引用字段
        person2.address.city = "Los Angeles";

        System.out.println(person1.address.city); // 输出 New York
        System.out.println(person2.address.city); // 输出 Los Angeles
    }
}

结果分析

  • person1person2Address 字段是独立的对象。
  • 修改 person2.address.city 不会影响 person1.address.city

方法 2:使用序列化实现深拷贝

通过序列化和反序列化实现深拷贝,适用于复杂对象结构。

import java.io.*;

class Person implements Serializable {
    String name;
    Address address;

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

    // 深拷贝方法
    public Person deepCopy() throws IOException, ClassNotFoundException {
        // 序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        // 反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (Person) ois.readObject();
    }
}

class Address implements Serializable {
    String city;

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

public class DeepCopyWithSerialization {
    public static void main(String[] args) throws Exception {
        Address address = new Address("New York");
        Person person1 = new Person("Alice", address);

        // 深拷贝
        Person person2 = person1.deepCopy();

        // 修改 person2 的引用字段
        person2.address.city = "Los Angeles";

        System.out.println(person1.address.city); // 输出 New York
        System.out.println(person2.address.city); // 输出 Los Angeles
    }
}

优点

  • 自动处理复杂对象结构。
  • 不需要手动编写深拷贝逻辑。

缺点

  • 性能较低(涉及序列化和反序列化)。
  • 被拷贝的类及其所有字段必须实现 Serializable 接口。

3. 浅拷贝与深拷贝的区别

特性浅拷贝深拷贝
复制内容只复制对象本身,引用类型字段共享递归复制对象及其所有引用类型字段
性能更快较慢(尤其是复杂对象结构)
适用场景对象的引用字段不需要独立时对象的引用字段需要完全独立时
实现难度简单(直接调用 clone() 或构造函数即可)较复杂(需手动或通过序列化实现)

4. 总结

  • 浅拷贝
    • 使用 clone() 方法实现。
    • 原对象和新对象共享引用字段。
  • 深拷贝
    • 手动实现或通过序列化实现。
    • 原对象和新对象完全独立。
  • 选择依据
    • 如果对象的引用字段不需要独立,使用浅拷贝。
    • 如果需要完全独立的对象,使用深拷贝。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值