`

java对象的复制

    博客分类:
  • java
 
阅读更多

今天看list和ArrayList的区别,发现了一个问题,

着实让我为我之前的代码出了一把汗,

之前做项目的时候用到了java的克隆,只是实现了Cloneable接口,

然后进行对象克隆并且复制、保存到数据库中,

 

为什么出汗,因为今天看到ArrayList的clone方法竟然是浅复制,

 

 

                ArrayList list1 = new ArrayList();
		list1.add(new Object());
		
		ArrayList list2 = (ArrayList) list1.clone();
		
		System.out.println(list1.get(0));
		System.out.println(list2.get(0));

 输出结果:

 

java.lang.Object@de6ced
java.lang.Object@de6ced

 

我勒个去,这两个list中的对象进入是同一个地址的,也就是说,相当于列表中的元素使用同一个对象:

 

 

                Object obj = new Object();
		ArrayList list1 = new ArrayList();
		list1.add(obj);
		
		ArrayList list2 = new ArrayList();
		list2.add(obj);

		System.out.println(list1.get(0));
		System.out.println(list2.get(0));

这样做有一个很大的问题,就是说如果obj对象不是一个Object对象,而是一个自定义的对象,那么obj的一个属性的修改就会影响到list1 和list2里面的两个值。

 

因为我之前写的代码就是先创建一个自定义类对象,

然后for循环,对这个对象克隆,然后赋予不同的值,

最后保存到数据库中,

你说你吓人么 。 

 

还好看到了光明:

 

备注:GenericCollection实现了Cloneable接口 

 

                GenericCollection gc = new GenericCollection();
		
		GenericCollection gc2 = (GenericCollection)gc.clone();
		
		System.out.println(gc);
		System.out.println(gc2);
		

 数据出结果:

 

 

com.hung.test.GenericCollection@18dfef8
com.hung.test.GenericCollection@15e83f9

 悬着的石头总算落地了,

 

 呵呵 这两个对象的地址不一样, 

 

说明之前写的程序不会有影响。

 

也说明了一个问题:

 

深复制:其实实现Cloneable接口的对象,调用clone方法的时候,并不是浅复制,而是创建了新的对象,并把每个属性值都重新赋给新对象的对应属性,

浅复制:其实只是把对象的应用地址给你复制了一分而已。

 

 

 

至此

 

给大家分享一下

欢迎拍砖 

 

-- 2012-10-25 11:48

 

 

 

 

添加说明 :

 

说明1:

其实,在Colneable接口的官方文档说明中,是建议覆盖object对象中的clone方法的,同时也建议调用super.clone()方法

但是我认为这样就多次一举了,如果要覆盖Object的clone方法,为什么还要调用super.clone()方法呢,自己定义就好了,可能是从性能方面考虑的吧,

 

但是这样也给用户提供了一个很好的机会,可以自定义clone方法,这样的话你就可以完全按照自己的意思来定制,

可以仅仅创建一个新对象返回,也可以创建对象之后给对象特定的字段赋值,这样就能打到定制化的效果。

非常好。

 

说明2:

完全可以只实现结构,而不覆盖Object中的clone方法,我亲自使过,可以的,因为Cloneable结构中没有定义任何方法。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics