Java中的深拷贝与浅拷贝

发布时间:2024年01月22日

深拷贝与浅拷贝

深拷贝和浅拷贝是编程中常用的两种对象复制方式,它们在复制对象时处理对象内部引用的方式上有所不同。

浅拷贝

浅拷贝(Shallow Copy)只复制对象的顶层结构,而不复制对象内部的引用对象。换句话说,浅拷贝只复制对象的值类型字段和引用类型字段的引用,而不复制引用对象本身。

  • 特点:如果原始对象中的字段是值类型,则复制其值;如果字段是引用类型,则复制引用地址而不是引用的对象本身。
  • 结果:浅拷贝后的新对象与原对象共享引用类型的成员。因此,修改其中一个对象的引用类型成员可能会影响另一个对象。

举例(伪代码):

original = { a: 1, b: { c: 2, d: 3 } }
shallowCopy = copy(original) // 浅拷贝
// shallowCopy = { a: 1, b: { c: 2, d: 3 } } 但 shallowCopy.b 和 original.b 指向同一个对象

深拷贝

深拷贝(Deep Copy)则是复制对象的所有层级结构。一个对象进行深拷贝后,不仅复制了对象的顶层结构,还复制了对象内部的所有引用对象。

  • 特点:无论是值类型还是引用类型,都会被完全复制到新对象中。
  • 结果:深拷贝后的对象与原对象不共享任何成员。修改一个对象的任何成员不会影响到另一个对象。

举例(伪代码):

original = { a: 1, b: { c: 2, d: 3 } }
deepCopy = deepcopy(original) // 深拷贝
// deepCopy = { a: 1, b: { c: 2, d: 3 } } 且 deepCopy.b 和 original.b 指向不同的对象

应用

浅拷贝通常用于复制不包含复杂对象或不需要独立操作引用对象的场景。而深拷贝则适用于需要完全独立的对象副本,或者当对象内部也包含引用对象时。

在不同的编程语言中,实现深拷贝和浅拷贝的方式可能不同。例如,在JavaScript中,可以使用Object.assign()或扩展运算符{...obj}实现浅拷贝,而深拷贝可能需要递归复制或使用如JSON.parse(JSON.stringify(obj))这样的技巧。在Python中,copy模块提供了copy()(浅拷贝)和deepcopy()(深拷贝)函数。

Java中的深拷贝与浅拷贝

在Java中,深拷贝和浅拷贝是处理对象复制时常见的两种方法,它们在处理对象内部引用时有本质的区别。

浅拷贝(Shallow Copy)

浅拷贝创建一个新的对象,然后将原始对象的非静态字段复制到新对象。如果字段是值类型(如基本数据类型),它将复制值;如果字段是引用类型,则复制引用但不复制引用的对象本身。

  • 实现方式:在Java中,浅拷贝通常可以通过使用Object.clone()方法来实现。为了使用clone()方法,类必须实现Cloneable接口并重写clone()方法。
  • 示例
    public class ShallowCopyExample implements Cloneable {
        private int[] data;
    
        public ShallowCopyExample() {
            data = new int[10];
            for (int i = 0; i < data.length; i++) {
                data[i] = i;
            }
        }
    
        public ShallowCopyExample clone() {
            try {
                return (ShallowCopyExample) super.clone();
            } catch (CloneNotSupportedException e) {
                return null;
            }
        }
    }
    

在这个例子中,clone()方法创建了ShallowCopyExample对象的浅拷贝。数组data的新引用被创建,但数组的内容并没有被复制。

深拷贝(Deep Copy)

深拷贝不仅复制对象及其字段,还递归复制它引用的所有对象。这意味着整个对象树都被复制了。

  • 实现方式:在Java中,实现深拷贝可以通过多种方式,例如递归复制所有对象、使用序列化/反序列化等。
  • 示例(使用序列化)
    import java.io.*;
    
    public class DeepCopyExample implements Serializable {
        private int[] data;
    
        public DeepCopyExample deepCopy() {
            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream out = new ObjectOutputStream(bos);
                out.writeObject(this);
    
                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
                ObjectInputStream in = new ObjectInputStream(bis);
                return (DeepCopyExample) in.readObject();
            } catch (IOException | ClassNotFoundException e) {
                return null;
            }
        }
    }
    

在这个例子中,deepCopy()方法通过序列化和反序列化对象来创建一个深拷贝。这种方法需要对象及其所有引用的对象都实现Serializable接口。

区别

  • 浅拷贝仅复制对象本身和对象内的引用地址,不复制引用的对象。
  • 深拷贝则完全复制了整个对象及其引用的所有对象,新对象与原对象之间不共享任何内容。

使用场景

  • 使用浅拷贝当你需要一个与原对象共享部分数据的独立对象时。
  • 使用深拷贝当你需要一个完全独立于原对象的副本时,例如,当你要修改新对象而不影响原对象的内部状态时。
文章来源:https://blog.csdn.net/m0_54187478/article/details/135744857
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。