java-深浅拷贝

深浅拷贝

深拷贝(Deep Copy) 和 浅拷贝(Shallow Copy) 是两种不同的对象复制方式,主要区别在于它们如何处理对象内部的引用类型字段。

一、浅拷贝(Shallow Copy)

浅拷贝是指创建一个新对象,然后将原对象的字段值复制到新对象中。对于基本数据类型,直接复制值;对于引用类型,复制的是引用(即内存地址),而不是引用指向的对象本身。

特点

  • 新对象和原对象共享引用类型的字段。
  • 修改其中一个对象的引用类型字段,会影响另一个对象。
  • 实现方式:
    1. 使用 clone() 方法(需实现 Cloneable 接口)。
    2. 手动复制字段。
  • 示例
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 address = new Address("Beijing");
       Person person1 = new Person("Alice", address);
       Person person2 = (Person) person1.clone();

       System.out.println(person1.address.city); // 输出: Beijing
       System.out.println(person2.address.city); // 输出: Beijing

       // 修改 person2 的 address
       person2.address.city = "Shanghai";

       // person1 的 address 也被修改
       System.out.println(person1.address.city); // 输出: Shanghai
   }
}

二、深拷贝(Deep Copy)

深拷贝是指创建一个新对象,并递归地复制原对象的所有字段,包括引用类型字段指向的对象。新对象和原对象完全独立,修改其中一个对象不会影响另一个对象。

特点

  • 新对象和原对象不共享任何引用类型的字段。
  • 修改其中一个对象的引用类型字段,不会影响另一个对象。
  • 实现方式:
    1. 手动递归复制所有字段。
    2. 使用序列化(Serialization)和反序列化(Deserialization)。
    3. 使用第三方库(如 Apache Commons Lang 的 SerializationUtils)。
  • 示例
import java.io.*;

class Address implements Serializable {
   String city;

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

class Person implements Serializable {
   String name;
   Address address;

   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();
   }
}

public class Main {
   public static void main(String[] args) throws IOException, ClassNotFoundException {
       Address address = new Address("Beijing");
       Person person1 = new Person("Alice", address);
       Person person2 = person1.deepCopy();

       System.out.println(person1.address.city); // 输出: Beijing
       System.out.println(person2.address.city); // 输出: Beijing

       // 修改 person2 的 address
       person2.address.city = "Shanghai";

       // person1 的 address 不受影响
       System.out.println(person1.address.city); // 输出: Beijing
   }
}

三、如果选择浅拷贝或者深拷贝

使用浅拷贝:

  • 当对象的引用类型字段不需要独立复制时。
  • 当对象结构简单,且性能要求较高时。

使用深拷贝:

  • 当对象的引用类型字段需要独立复制时。
  • 当对象结构复杂,且需要完全独立的副本时。

深拷贝其他方式

手动递归复制:

  • 对于每个引用类型字段,手动创建新对象并复制数据。

使用第三方库:

  • 如 Apache Commons Lang 的 SerializationUtils.clone():
Person person2 = SerializationUtils.clone(person1);

总结

  • 浅拷贝:复制引用,共享对象,适合简单场景。
  • 深拷贝:复制对象,完全独立,适合复杂场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在下陈平安

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值