java中浅拷贝与深拷贝快速理解区分 -java基础复习部分

这里旨在快速理解与区分深拷贝与浅拷贝的区别。

深拷贝与浅拷贝概念的区分

  ClassM A = new ClassM();
  ClassM B = A.clone();

浅拷贝:A与B是两个对象,但是它们之间存在着关联。当修改A.a(引用类型)时,B.a也会跟着被改变
。也就是A与B有公共部分,修改这个公共部分(ClassM中的引用类型字段),相当于对A与B都进行了修改。
深拷贝:A与B是两个对象,它们之间不存在关联,修改A对B毫无影响。它们相互独立

为和会有深拷贝与浅拷贝

浅拷贝实例代码(拷贝自cs-note)

public class ShallowCloneExample implements Cloneable {
    
    

    private int[] arr;

    public ShallowCloneExample() {
    
    
        arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
    
    
            arr[i] = i;
        }
    }

    public void set(int index, int value) {
    
    
        arr[index] = value;
    }

    public int get(int index) {
    
    
        return arr[index];
    }

    @Override
    protected ShallowCloneExample clone() throws CloneNotSupportedException {
    
    
        return (ShallowCloneExample) super.clone();
    }
}
ShallowCloneExample e1 = new ShallowCloneExample();
ShallowCloneExample e2 = null;
try {
    
    
    e2 = e1.clone();
} catch (CloneNotSupportedException e) {
    
    
    e.printStackTrace();
}
e1.set(2, 222);
System.out.println(e2.get(2)); // 222

深拷贝实例代码

public class DeepCloneExample implements Cloneable {
    
    

    private int[] arr;

    public DeepCloneExample() {
    
    
        arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
    
    
            arr[i] = i;
        }
    }

    public void set(int index, int value) {
    
    
        arr[index] = value;
    }

    public int get(int index) {
    
    
        return arr[index];
    }

    @Override
    protected DeepCloneExample clone() throws CloneNotSupportedException {
    
    
        DeepCloneExample result = (DeepCloneExample) super.clone();
        result.arr = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
    
    
            result.arr[i] = arr[i];
        }
        return result;
    }
}
DeepCloneExample e1 = new DeepCloneExample();
DeepCloneExample e2 = null;
try {
    
    
    e2 = e1.clone();
} catch (CloneNotSupportedException e) {
    
    
    e.printStackTrace();
}
e1.set(2, 222);
System.out.println(e2.get(2)); // 2

从上面两个示例代码可以看出,二者的类中都有一个int[] arr的引用类型。
java中只有值传递,对于基本类型来说,直接拷贝值,就不存在问题;而对于引用类型来说,拷贝的也是值,但是地址值,所以就存在着问题了。

在浅拷贝示例代码中,e1与e2的arr字段因为浅拷贝的缘故,其值都是一个对象的地址值,也就是它俩都指向一个对象,那么自然修改e1的arr,e2的arr也会被修改了。
而深拷贝实例代码中,因为在复写clone方法时,将arr中的基本类型int值也进行了拷贝,还new了一个新的数组,所以就不存在什么引用类型的问题,e1和e2的arr明显指向的是不同的对象。故e1和e2不存在关联。

这里用俩示意图来展示深拷贝与浅拷贝的思路。
(图片来自:Java 浅拷贝和深拷贝,博客地址见本文尾)
在这里插入图片描述
在这里插入图片描述

相关思考

那有人就会问,你上面的深拷贝实例代码不就对拷贝了一层吗,如果arr是一个List<List>,你怎么办呢?
对此,我个人的理解是,深拷贝就是让拷贝的对象与被拷贝的对象之间相互独立,毫无关系,那么当引用类型有嵌套时,则需要将clone的代码进行修改,保证拷贝的时候,拷贝到基本类型的那一层,让两对象毫无联系才对。
然后看到有其他网友说是通过序列化和反序列化来实现深拷贝,我觉得有理,不过具体怎么实现还是看具体的应用场景,只要俩对象无关联,我便觉得其就是深拷贝,反之就是浅拷拷贝。

参考资料

cs-note
Java 浅拷贝和深拷贝

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/112554713