java对象复制

来源:互联网 发布:mac有steam吗 编辑:程序博客网 时间:2024/05/16 11:43
 

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

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

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

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

 

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

 

 

Java代码  收藏代码
  1.               ArrayList list1 = new ArrayList();  
  2. list1.add(new Object());  
  3.   
  4. ArrayList list2 = (ArrayList) list1.clone();  
  5.   
  6. System.out.println(list1.get(0));  
  7. System.out.println(list2.get(0));  

 输出结果:

 

Java代码  收藏代码
  1. java.lang.Object@de6ced  
  2. java.lang.Object@de6ced  

 

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

 

 

Java代码  收藏代码
  1.               Object obj = new Object();  
  2. ArrayList list1 = new ArrayList();  
  3. list1.add(obj);  
  4.   
  5. ArrayList list2 = new ArrayList();  
  6. list2.add(obj);  
  7.   
  8. System.out.println(list1.get(0));  
  9. System.out.println(list2.get(0));  

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

 

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

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

最后保存到数据库中,

你说你吓人么 。 

 

还好看到了光明:

 

备注:GenericCollection实现了Cloneable接口 

 

Java代码  收藏代码
  1.               GenericCollection gc = new GenericCollection();  
  2.   
  3. GenericCollection gc2 = (GenericCollection)gc.clone();  
  4.   
  5. System.out.println(gc);  
  6. System.out.println(gc2);  

 数据出结果:

 

 

Java代码  收藏代码
  1. com.hung.test.GenericCollection@18dfef8  
  2. 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结构中没有定义任何方法。