JAVA复制一个对象:浅拷贝与深拷贝详解

1. 浅拷贝

浅拷贝是一种简单的复制方法,它创建一个新的对象,并复制原始对象的所有非静态字段到新对象。如果字段是值类型,那么会进行逐位复制;如果字段是引用类型,那么复制的是引用而不是实际的对象,这意味着,原始对象和复制的对象将共享同一个引用类型的字段
下面是一个简单的例子:

public class Student implements Cloneable {  
    int id;  
    String name;  
    OtherObject other;  
  
    // ... 构造方法、getter和setter ...  
  
    @Override  
    public Student clone() {  
        try {  
            return (Student) super.clone();  
        } catch (CloneNotSupportedException e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
}

在这个例子中,当你调用clone()方法时,你得到一个新的Student对象,它的idname字段与原始对象相同,但other字段仍然是原始对象的引用,这意味着,如果你更改了复制的对象的other字段,原始对象的other字段也会被更改

2. 深拷贝

2.1. 手动实现深拷贝

对于每个引用类型的字段,你需要手动创建新的实例并进行赋值,这种方法需要大量的代码,并且容易出错

2.2. 克隆

你可以在每个引用类型字段上实现Cloneable接口并重写clone()方法,这需要为每个引用类型字段编写额外的代码来创建新的实例

2.3. 使用序列化与反序列化

这是实现深拷贝的一种更简单的方法。你可以将对象序列化为字节数组,然后再将字节数组反序列化为新的对象。这种方法的好处是它可以处理复杂的对象图,但需要注意的是,所有的相关对象也必须实现序列化接口
下面是一个简单的例子:

import java.io.*;  
  
public class DeepCopyExample {  
    public static void main(String[] args) throws IOException, ClassNotFoundException {  
        // 创建一个原始对象  
        OriginalObject original = new OriginalObject("Hello", "World");  
        System.out.println("原始对象:");  
        System.out.println(original);  
  
        // 深拷贝原始对象  
        OriginalObject copy = deepCopy(original);  
        System.out.println("\n复制后的对象:");  
        System.out.println(copy);  
  
        // 修改原始对象的引用字段  
        original.setOtherObject("Modified");  
        System.out.println("\n修改原始对象的引用字段:");  
        System.out.println(original);  
  
        // 打印复制后的对象,验证深拷贝的正确性  
        System.out.println("\n复制后的对象(验证深拷贝):");  
        System.out.println(copy);  
    }  
  
    /**  
     * 深拷贝方法,用于创建对象的副本。  
     * 这里使用序列化与反序列化的方式实现深拷贝。  
     */  
    public static <T extends Serializable> T deepCopy(T obj) throws IOException, ClassNotFoundException {  
        // 将对象序列化为字节数组  
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        ObjectOutputStream out = new ObjectOutputStream(bos);  
        out.writeObject(obj);  
        out.flush();  
        out.close();  
        byte[] bytes = bos.toByteArray();  
  
        // 从字节数组反序列化对象  
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);  
        ObjectInputStream in = new ObjectInputStream(bais);  
        @SuppressWarnings("unchecked")  
        T copy = (T) in.readObject();  
        in.close();  
        bais.close();  
  
        return copy;  
    }  
}  
  
// 示例对象类,实现Serializable接口以支持序列化与反序列化  
class OriginalObject implements Serializable {  
    private static final long serialVersionUID = 1L;  
    private String field1;  
    private OtherObject field2;  
  
    public OriginalObject(String field1, String field2) {  
        this.field1 = field1;  
        this.field2 = new OtherObject(field2); // 假设OtherObject类也实现了Serializable接口  
    }  
  
    public String getField1() {  
        return field1;  
    }  
  
    public void setField1(String field1) {  
        this.field1 = field1;  
    }  
  
    public OtherObject getOtherObject() {  
        return field2;  
    }  
  
    public void setOtherObject(String otherObject) {  
        this.field2 = new OtherObject(otherObject); // 重新创建OtherObject实例,确保深拷贝的正确性  
    }  
  
    @Override  
    public String toString() {  
        return "OriginalObject{" + "field1='" + field1 + '\'' + ", field2=" + field2 + '}';  
    }  
}  
  
// 示例引用类型类,实现Serializable接口以支持序列化与反序列化(这里只是简单示例,实际中可能有更复杂的类结构)  
class OtherObject implements Serializable {  
    private static final long serialVersionUID = 1L;  
    private String name;  
  
    public OtherObject(String name) {  
        this.name = name;  
    }  
  
    public String getName() {  
        return name;  
    }  
}

2.4. 使用库或框架

有一些库或框架可以帮助你更容易地实现深拷贝,例如:

  • Apache Commons LangSerializationUtils.clone()方法
  • GoogleGuava库的ImmutableCopy类
  • 工具类BeanUtilsPropertyUtils进行对象复制
  • Hutool——ObjectUtil

这些工具可以简化深拷贝的实现,并处理许多常见的边界情况

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深拷贝浅拷贝是在对象复制过程中常用的两种方式,它们的区别在于复制后的对象与原始对象之间的关系。 浅拷贝(Shallow Copy)是创建一个对象,该对象与原始对象的元素是对原始对象中元素的引用。换言之,复制后的对象与原始对象共享内部对象的引用。当修改原始对象中的可变元素时,这些修改也会反映在复制后的对象中。 深拷贝(Deep Copy)则是创建一个全新的独立对象复制后的对象与原始对象完全独立,互不影响。深拷贝会递归地复制原始对象及其内部所有可变对象,而不仅仅是引用。 举个例子来说明: ```python import copy # 原始对象 original_list = [1, 2, [3, 4]] # 浅拷贝 shallow_copy = copy.copy(original_list) # 深拷贝 deep_copy = copy.deepcopy(original_list) # 修改原始对象中的可变元素 original_list[0] = 10 original_list[2].append(5) print(original_list) # 输出: [10, 2, [3, 4, 5]] print(shallow_copy) # 输出: [10, 2, [3, 4, 5]] print(deep_copy) # 输出: [1, 2, [3, 4]] ``` 在上面的例子中,原始对象一个列表 `original_list`,其中包含一个整数和一个列表。通过浅拷贝 `copy.copy()` 和深拷贝 `copy.deepcopy()` 分别创建了复制对象 `shallow_copy` 和 `deep_copy`。 当我们修改原始对象的第一个元素和第三个元素的子列表时,可以看到浅拷贝对象也受到了影响,而深拷贝对象保持不变。 因此,在需要创建独立的对象副本且避免修改原始对象时,深拷贝是更安全和可靠的选择,而浅拷贝则更适合在一些特定场景下节省内存或共享数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值