关于clone() 浅拷贝 和深拷贝 通过例子分析

结论:

浅拷贝:
Object的clone() 会返回一个与原对象不同的引用,但是是浅拷贝,即拷贝后的成员与原对象的成员是引用的相同的地址,即整个对象引用不同,成员引用相同

如下图:浅拷贝对象有不同的散列值,但是成员数组引用相同,修改其中一个,另一个也相应改变
在这里插入图片描述

深拷贝
对于自定义类型,在实现Cloneable接口的基础上,可以重写clone()函数,这里可以手动对成员引用指向不同的值,这样,就实现了深拷贝

以下代码在去掉注释后的运行结果:
在这里插入图片描述

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;
    }
}
clone() 的替代方案

使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。

public class CloneConstructorExample {

    private int[] arr;

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

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

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

    public int get(int index) {
        return arr[index];
    }
}
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
posted @ 2022-11-17 23:02  林动  阅读(8)  评论(0编辑  收藏  举报