原博文:http://blog.csdn.net/qq_29329775/article/details/49516247
最近在做算法作业时出现了错误,原因是没有弄清楚java集合的深度复制和浅度复制的区别。
1.首先是对Java集合对象得浅复制与深度复制的理解
普通的集合复制只是将内存中栈的地址快拷贝一份,使得一个新的集合对象指向这个地址块,但是集合中的对象变量却是指向堆中的同一块区域。所以当拷贝的集合修改了集合对象内的数据,那么源集合对象也就随之改变了,这样的效果我们称之为Java集合对象的浅复制,即只是在栈中拷贝了,而堆中的数据并没有拷贝。而深度复制则是同时在栈中和堆中的数据进行拷贝,这样,其拷贝的集合和被拷贝的集合已经没有任何关系了。
2.一个例子
新建一个Demo类
1 public class Demo { 2 3 private int demoValue; 4 5 public void setDemoValue(int value){ 6 this.demoValue = value; 7 } 8 9 public int getDemoValue(){ 10 return this.demoValue; 11 } 12 13 public Demo(){ 14 15 } 16 17 public Demo(int demoValue){ 18 this.demoValue = demoValue; 19 } 20 }
接下来,我们试验一下浅复制:
1 @Test 2 public void testCommonCopy() { 3 4 // Here I create a source collection. 5 ArrayList<Demo> sourceCollection = new ArrayList<Demo>(); 6 7 // Here I add some objects to sourceCollection. 8 sourceCollection.add(new Demo(1)); 9 sourceCollection.add(new Demo(2)); 10 11 // Here I create a new empty collection. 12 ArrayList<Demo> newCollection = new ArrayList<Demo>(); 13 newCollection.addAll(sourceCollection); 14 15 // Now I modify some objects in new collection. 16 newCollection.get(0).setDemoValue(3); 17 18 // Now We verify what it is inside the source collection. 19 for(Demo demo : sourceCollection){ 20 System.out.println(demo.getDemoValue()); 21 } 22 23 // Now I verify if the source Collection is modified. 24 Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1); 25 }
对其的执行结果,很明显,newCollection中改变的Demo对象在SourceCollection中也跟着改变了,这说明两个集合中的Demo对象是同一个对象。这也是浅复制所存在的弊端。那么如何将两个集合独立开来呢,即如何进行深度复制,我们不烦继续往下阅读:
首先我们先对Demo类作一下处理,使其实现Cloneable接口,并重写它的clone方法
1 protected Demo clone() throws CloneNotSupportedException { 2 return (Demo)super.clone(); 3 }
然后我们来进行深度复制:
1 @Test 2 public void testCopyDeep() throws Exception{ 3 ArrayList<Demo> sourceCollection = new ArrayList<Demo>(); 4 sourceCollection.add(new Demo(1)); 5 sourceCollection.add(new Demo(2)); 6 7 ArrayList<Demo> newCollection = new ArrayList<Demo>(); 8 for(Demo demo : sourceCollection){ 9 newCollection.add(demo.clone()); 10 } 11 newCollection.get(0).setDemoValue(3); 12 for(Demo demo : sourceCollection){ 13 System.out.println(demo.getDemoValue()); 14 } 15 Assert.assertEquals(sourceCollection.get(0).getDemoValue(),1); 16 }
最后我们来观察一下结果:搞定
接下来我们来分析一下出现这个现象的原因:
深度复制:如图:A中具有X1,X2,X3...Xn的数据,深度复制则对其每个堆和栈中的数据都进行一次拷贝,生成对应的Y1,Y2,Y3以及B对象。此时,A与B已经分别存放在不同的地址单元,所以A中改了数据,B中的数据不变,反之亦然。
浅复制:如图:A复制成B,但是A和B中的数据均指向同一个X1,X2,X3...Xn,所以当A通过某种方法改变了数据,对于B来说,其中的数据也改变了。
原文博客:http://blog.csdn.net/qq_29329775/article/details/49516247