Java集合对象的深度复制与普通复制

转载自:https://blog.csdn.net/qq_29329775/article/details/49516247
001-首先是对Java集合对象得浅复制与深度复制的理解
最近在开发中遇到了一些关于集合复制的一些问题,普通的集合复制只是将内存中栈的地址快拷贝一份,使得一个新的集合对象指向这个地址块,但是集合中的对象变量却是指向堆中的同一块区域。所以当拷贝的集合修改了集合对象内的数据,那么源集合对象也就随之改变了,这样的效果我们称之为Java集合对象的浅复制,即只是在栈中拷贝了,而堆中的数据并没有拷贝。以下是Wiki上关于浅复制的定义:

One method of copying an object is the shallow copy. In that case a new object B is created, and the fields values of A are copied over to B. If the field value is a reference to an object (e.g., a memory address) it copies the reference, hence referring to the same object as A does, and if the field value is a primitive type it copies the value of the primitive type. In languages without primitive types (where everything is an object), all fields of the copy B are references to the same objects as the fields of original A. The referenced objects are thus shared, so if one of these objects is modified (from A or B), the change is visible in the other. Shallow copies are simple and typically cheap, as they can be usually implemented by simply copying the bits exactly.
而深度复制则是同时在栈中和堆中的数据进行拷贝,这样,其拷贝的集合和被拷贝的集合已经没有任何关系了。同样,在Wiki上的定义如下:
An alternative is a deep copy, meaning that fields are dereferenced: rather than references to objects being copied, new copy objects are created for any referenced objects, and references to these placed in B. The result is different from the result a shallow copy gives in that the objects referenced by the copy B are distinct from those referenced by A, and independent. Deep copies are more expensive, due to needing to create additional objects, and can be substantially more complicated, due to references possibly forming a complicated graph.

002-接下来我们来看一个简单的例子

public class Demo {  
          
    private int  demoValue;  
          
    public void setDemoValue(int value){  
        this.demoValue = value;  
    }  
          
    public int getDemoValue(){  
        return this.demoValue;  
    }  
          
    public Demo(){  
              
    }  
          
    public Demo(int demoValue){  
        this.demoValue = demoValue;  
    }  
}

接下来,我们试验一下浅复制:

public void testCommonCopy() {  
  
    // Here I create a source collection.  
    ArrayList<Demo> sourceCollection = new ArrayList<Demo>();  
  
    // Here I add some objects to sourceCollection.  
    sourceCollection.add(new Demo(1));  
    sourceCollection.add(new Demo(2));  
  
    // Here I create a new empty collection.  
    ArrayList<Demo> newCollection = new ArrayList<Demo>();  
    newCollection.addAll(sourceCollection);  
  
    // Now I modify some objects in new collection.  
    newCollection.get(0).setDemoValue(3);  
      
    // Now We verify what it is inside the source collection.  
    for(Demo demo : sourceCollection){  
        System.out.println(demo.getDemoValue());  
    }  
      
    // Now I verify if the source Collection is modified.  
    Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1);  
}  

这里写图片描述

对其的执行结果,很明显,newCollection中改变的Demo对象在SourceCollection中也跟着改变了,这说明两个集合中的Demo对象是同一个对象。这也是浅复制所存在的弊端。那么如何将两个集合独立开来呢,即如何进行深度复制,我们不烦继续往下阅读:

首先我们先对Demo类作一下处理,使其实现Cloneable接口,并重写它的clone方法:

 @Override  
protected Demo clone() throws CloneNotSupportedException {             
return (Demo)super.clone();

然后我们来进行深度复制:

public void testCopyDeep() throws Exception{  
    ArrayList<Demo> sourceCollection = new ArrayList<Demo>();  
    sourceCollection.add(new Demo(1));  
    sourceCollection.add(new Demo(2));    
      
    ArrayList<Demo> newCollection = new ArrayList<Demo>();  
    for(Demo demo : sourceCollection){  
        newCollection.add(demo.clone());  
    }  
    newCollection.get(0).setDemoValue(3);  
    for(Demo demo : sourceCollection){  
        System.out.println(demo.getDemoValue());  
    }  
    Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1);  
}  

这里写图片描述
接下来我们来分析一下出现这个现象的原因:

深度复制:如图:A中具有X1,X2,X3…Xn的数据,深度复制则对其每个堆和栈中的数据都进行一次拷贝,生成对应的Y1,Y2,Y3以及B对象。此时,A与B已经分别存放在不同的地址单元,所以A中改了数据,B中的数据不变,反之亦然。

浅复制:如图:A复制成B,但是A和B中的数据均指向同一个X1,X2,X3…Xn,所以当A通过某种方法改变了数据,对于B来说,其中的数据也改变了。

最后,给大家推荐一下Wiki上的关于对象复制的文章,https://en.wikipedia.org/wiki/Object_copying。
也给大家推荐一下我的个人博客,虽然已经好久没有更新了。http://andersonlu.github.io/ALBOG/
同时也希望大家能够在本篇文章中收益,感谢大家的阅读。记得点赞哦!

                                                                 笔者:Anderson Lu
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值