深拷贝和浅拷贝

150 阅读3分钟

最近看文章里提到了深拷贝和浅拷贝,于是又复习了一下,记一点笔记~

拷贝 顾名思义就是复制一份一样的对象,只不过对象的内容相同,地址不同。实现对象的拷贝要将该对象实现Cloneable接口,并实现clone方法,通过clone方法来实现对象的拷贝。

接下来我创建一个banana对象。

 public class Banana {
    //不同香蕉的价格
    private int[] prices;
    //购买香蕉的数量
    private int size;
    set()...
    get()...
    toString()...
}

浅拷贝: 克隆对象进行修改操作之后被克隆对象也会被修改,对于基本数据类型的变量会重新复制一份,而对于引用类型的变量只是对引用进行拷贝,克隆对象和被克隆对象指向的是一个堆内存地址。 浅拷贝代码如下,实现Cloneable,实现clone()方法:

class Banana implements Cloneable{
    private int[] prices;
    private int size;
    
    set()...
    get()...

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
   toString()...
}

当我们在main方法中执行如下代码:

 public static void main(String[] args) throws CloneNotSupportedException {
       int [] prices = new int[2];
        prices[0] = 10;
        prices[1] = 20;
        Banana b1 = new Banana();
        b1.setSize(11);
        b1.setPrices(prices);
        System.out.println("banana1  初始化" + b1.toString());
        Banana b2 = (Banana) b1.clone();
        System.out.println("banana2克隆之后" + b2.toString());
        int[] prices1 = b2.getPrices();
        prices1[0] = 21;
        b2.setSize(5);
        System.out.println("banana2更改之后" + b2.toString());
        System.out.println("banana1    后续" + b1.toString());
    }

运行结果如下:

banana1  初始化Banana 2133927002 {prices=[10, 20], size='11'}
banana2克隆之后Banana 1836019240 {prices=[10, 20], size='11'}
banana2更改之后Banana 1836019240 {prices=[21, 20], size='5'}
banana1    后续Banana 2133927002 {prices=[21, 20], size='11'}

我们可以看到banana2克隆banban1之后,两个对象地址不同,属性相同,但是在修改banana2之后banan1的值也会被修改,所以这就是上面浅拷贝的概念,原因呢如下图:

两个栈中的指针都是指向了同一个banana对象,所以不管修改哪个,修改的都是同一个banana。

深拷贝: 对对象及该对象关联的对象内容,都会进行一份拷贝,克隆对象进行修改操作之后被克隆对象不会被修改,克隆对象和被克隆对象除了属性一样以外(是属性不是属性值哦~),两者没有关系。 深拷贝代码如下,实现Cloneable接口,重写clone()方法:

class Banana implements Cloneable{
    private int[] prices;
    private int size;
    
    set()...
    get()...

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Banana banana = (Banana) super.clone();
        banana.prices = prices.clone();
        return banana;
    }
    
   toString()...
}

运行结果如下:

banana1  初始化Banana 2133927002 {prices=[10, 20], size='11'}
banana2更改之前Banana 1836019240 {prices=[10, 20], size='11'}
banana2更改之后Banana 1836019240 {prices=[21, 20], size='5'}
banana1    后续Banana 2133927002 {prices=[10, 20], size='11'}

我们可以看到banana2修改价格和数量之后,banan1并不会被修改,这就是上面深拷贝的概念,原因如下: 两个栈中的指针banana1和banana2分别指向了两个不同的banana对象地址,所以修改了banan1的属性之后不会影响到banan2,两个对象之间是独立的,并且在clone()方法中,将修改之后的prices克隆之后赋值给了banana的prices,然后返回修改后的banana,从而实现了深克隆,但是这样如果属性太多的话,一个一个来太麻烦了,我们可以使用java流中的序列化来对对象进行深克隆,下次再给细说,过年收拾家里太累了,先睡觉(ㄒoㄒ) 。末尾推荐一个顺丰程序员的公众号,文章通俗易懂,讲的也比较深入,非常适合小白阅读!