深拷贝和浅拷贝

深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是对象复制的两种方式,核心区别在于是否递归复制对象内部的所有引用类型成员。以下是详细对比与实现方法:


1. 核心区别

特性浅拷贝深拷贝
复制范围仅复制对象本身(值类型字段)和引用地址递归复制对象及其所有引用类型成员的全新实例
内存影响引用类型字段与原对象共享同一内存地址所有引用类型字段均创建独立副本
修改影响修改副本的引用类型字段会影响原对象副本与原对象完全独立,互不影响
实现复杂度简单(默认clone()即可)复杂(需手动处理所有嵌套对象)
性能开销高(尤其嵌套层级深时)

2. 代码示例(Java)​

示例类定义
 

java

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

    // 浅拷贝实现
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.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(); // 默认浅拷贝
    }

    // 深拷贝实现(手动递归复制)
    public Person deepCopy() throws CloneNotSupportedException {
        Person copy = (Person) super.clone();
        copy.address = (Address) address.clone(); // 递归复制引用类型字段
        return copy;
    }
}
测试代码
 

java

public static void main(String[] args) throws CloneNotSupportedException {
    Address address = new Address("北京");
    Person p1 = new Person("张三", address);
    
    // 浅拷贝测试
    Person p2Shallow = (Person) p1.clone();
    p2Shallow.address.city = "上海";
    System.out.println(p1.address.city); // 输出"上海"(原对象被修改)

    // 深拷贝测试
    Person p2Deep = p1.deepCopy();
    p2Deep.address.city = "广州";
    System.out.println(p1.address.city); // 输出"上海"(原对象未受影响)
}

3. 实现方式对比

浅拷贝
  • 默认行为:Java的Object.clone()方法(需实现Cloneable接口)。
  • 适用场景:对象仅包含基本类型字段或不可变引用(如String)。
深拷贝
  • 手动递归实现:逐层调用引用类型字段的clone()方法。
  • 序列化/反序列化:通过对象流实现完全独立副本。
     

    java

    public static <T> T deepCopyBySerialization(T obj) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (T) ois.readObject();
    }
  • 工具库:使用Apache Commons Lang的SerializationUtils.clone()
     

    java

    Person copy = SerializationUtils.clone(p1);

4. 注意事项

  • 性能问题:深拷贝可能因递归复制或序列化导致高延迟。
  • 循环引用:对象内部存在循环引用时需特殊处理,避免栈溢出。
  • 不可变对象:如String、Integer等无需深拷贝,直接引用即可。
  • Cloneable接口:若未实现,调用clone()会抛出CloneNotSupportedException

5. 设计建议

  • 优先使用深拷贝:当对象需要完全独立时(如缓存数据、线程安全场景)。
  • 避免过度复制:对只读数据或不可变对象使用浅拷贝。
  • 替代方案:使用Builder模式或工厂方法创建新对象,而非依赖拷贝。

总结

  • 浅拷贝:复制速度快,但共享引用对象,适用于简单数据。
  • 深拷贝:数据完全隔离,适用于复杂对象或需要线程安全的场景。
    根据业务需求选择合适的拷贝方式,在性能与数据独立性之间取得平衡。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值