对象的深拷贝

68 阅读3分钟

最近在做标签系统时,为提高查询效率,使用了内存map,在初始化时将数据查询放在内存中,在查询时,不再去查数据库,而是使用map中的数据进行关联查询。在使用内存时,有时需要对查询结果重新赋值,如某些没有权限的字段需要赋值“暂无权限”等,就出现了内存会被修改的问题。

1、简单介绍下深拷贝和浅拷贝

浅拷贝:只复制对象的引用,两个引用仍然指向同一个对象,在内存中占用同一块内存;

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象;

换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量;

那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象;

换言之,深复制把要复制的对象所引用的对象都复制了一遍

2、再说说我们遇到的问题,在对对象进行=赋值,或者clone时候一般都是我们所说的浅复制,Object T1= T2;也就是说我们获取的并非在堆中重新分配的一块内存,而是一个指向原有数据内存的一个引用。这样的后果就是我们修改了T1中的属性,那么T2的属性也会同时发生变化,因为他们两个本身就指向同一个对象,所以变化一个另外一个也随着变化。

一般来说我们常用的解决写法是:在Map中提供的一个putAll方法,可以部分解决这个问题,(为什么说是部分呢?因为putAll方法只能对基本数据类型进行深复制,对于对象类型完全也是无力),那么就需一个更好的解决方案来进行对象的深复制

有一个方法是,使用序列化Serializable这个接口可以完成深拷贝的操作,但遗憾的是Map对象并没有实现Serializable接口,不能直接对接口进行深复制操作。

但是作为Map的子类,HashMap实现了Serialization,因此可以通过以下的方式实现深复制。

下面简单说说java 深拷贝map 深度复制map可以用的解决方法

方法1使用依赖:

使用jar包commons-lang-2.4.jar中的 SerializationUtils.clone() 方法

方法2写工具方法

 class CloneUtils{

   @SuppressWarnings("unchecked")

   public static < T extends Serializable > T clone(T obj){

         T cloneObj=null;

         try{

             //读取对象字节数据

             ByteArrayOutputStream baos=new ByteArrayOutputStream();

             ObjectOutputStream oos=new ObjectOutputStream(baos);

             oos.writeObject(obj);

             oos.close();

             //分配内存空间,写入原始对象,生成新对象

             ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());

             ObjectInputStream ois=new ObjectInputStream(bais);

             //返回新的对象,并做类型转换

             cloneObj=(T)ois.readObject();

             ois.close();

         }catch(Exception e){

             e.printStackTrace();

         }

         return cloneObj;

     }

}