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

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-接下来我们来看一个简单的例子

如下,建立一个Demo类:
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;
	}
}
接下来,我们试验一下浅复制:
        @Test
	public void testCommonCopy() {

		// Here I create a source collection.
		ArrayList sourceCollection = new ArrayList();

		// 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 newCollection = new ArrayList();
		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);
	}
Java集合对象的深度复制与普通复制_第1张图片
    对其的执行结果,很明显,newCollection中改变的Demo对象在SourceCollection中也跟着改变了,这说明两个集合中的Demo对象是同一个对象。这也是浅复制所存在的弊端。那么如何将两个集合独立开来呢,即如何进行深度复制,我们不烦继续往下阅读:

首先我们先对Demo类作一下处理,使其实现Cloneable接口,并重写它的clone方法:
                @Override
		protected Demo clone() throws CloneNotSupportedException {			
			return (Demo)super.clone();
		}
然后我们来进行深度复制:
	@Test
	public void testCopyDeep() throws Exception{
		ArrayList sourceCollection = new ArrayList();
		sourceCollection.add(new Demo(1));
		sourceCollection.add(new Demo(2));	
		
		ArrayList newCollection = new ArrayList();
		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);
	}

最后我们来观察一下结果:搞定

Java集合对象的深度复制与普通复制_第2张图片
接下来我们来分析一下出现这个现象的原因:

深度复制:如图: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



你可能感兴趣的:(Java)