首页 > 技术文章 > Map,List,POJO深拷贝(序列化实现)方法与注意事项

top37 2018-01-25 18:15 原文

转载请注明出处,谢谢!

方法1:

 1   /*jdk >= 1.5*/
 2     @SuppressWarnings("unchecked")
 3     public static <T> T deepClone(T obj) {
 4         T clonedObj = null;
 5         ObjectOutputStream oos = null;
 6         ObjectInputStream ois = null;
 7         try {
 8             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 9             oos = new ObjectOutputStream(baos);
10             oos.writeObject(obj);
11             ByteArrayInputStream bais = new ByteArrayInputStream(
12                     baos.toByteArray());
13             ois = new ObjectInputStream(bais);
14             clonedObj = (T) ois.readObject();
15         } catch (Exception e) {
16             e.printStackTrace();
17         } finally {
18             try {
19                 oos.close();
20                 ois.close();
21             } catch (IOException e) {
22                 e.printStackTrace();
23             }
24 
25         }
26         return clonedObj;
27     }

方法2:

 1    /*jdk >= 1.7*/
 2     @SuppressWarnings("unchecked")
 3     public static <T> T deepCopy(T srcObj) {
 4         T targetObj = null;
 5         try 
 6         (
 7             ByteArrayInputStream bais = new ByteArrayInputStream(deepCopyRepo(srcObj, new ByteArrayOutputStream()).toByteArray());
 8             ObjectInputStream ois = new ObjectInputStream(bais)
 9         ) 
10         {
11             targetObj = (T) ois.readObject();
12         } 
13         catch (Exception e) 
14         {
15             e.printStackTrace();
16         } 
17         return targetObj;
18     }
19     public static ByteArrayOutputStream deepCopyRepo(Object obj,ByteArrayOutputStream baos) throws Exception {
20         try 
21         (
22             ObjectOutputStream oos = new ObjectOutputStream(baos)
23         ) 
24         {
25             oos.writeObject(obj);
26         }
27         return baos;
28     }

 注意事项:

1.若Java 7 build 105 版本及以上,推荐使用方法2;try-with-resources语句,ARM(Automatic Resource Management) 自动资源管理

2.被拷贝对象必须为可序列化的;当然,常用的如HashMap,ArrayList都是实现序列化的,直接使用本方法即可。

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

示例POJO:

 1 import java.io.Serializable;
 2 import java.util.List;
 3 
 4 public class Person implements Serializable{
 5     /*自定义版本*/
 6     private static final long serialVersionUID = 1L;
 7     
 8     private String name;
 9     private List<Person> children;
10     /*age属性因transient修饰,所以被序列化机制隔离*/
11     private transient int age;
12     public Person(String name,List<Person> children,int age){
13         this.name = name;
14         this.children = children;
15         this.age = age;
16     }
17     public Person(){}
18     public String getName() {
19         return name;
20     }
21     public void setName(String name) {
22         this.name = name;
23     }
24     public List<Person> getChildren() {
25         return children;
26     }
27     public void setChildren(List<Person> children) {
28         this.children = children;
29     }
30     public int getAge() {
31         return age;
32     }
33     public void setAge(int age) {
34         this.age = age;
35     }
36     @Override/*根据jvm返回的hashCode判断对象相同*/
37     public String toString() {
38         return "Person"+ "@" + Integer.toHexString(this.hashCode())+" [name=" + name + ", children=" + children + ", age="
39                 + age + "]";
40     }
41 }

junit:

 1   @Test
 2     public void testDeepCopy(){
 3         List<Person> children = new ArrayList<>();
 4         Person daughter = new Person("daughter",null,3);
 5         Person son = new Person("son",null,1);
 6         children.add(son);children.add(daughter);
 7         Person father = new Person("sqiang",children,29);
 8         System.out.println(father);
 9         Person cfather = Utils.deepCopy(father);
10         System.out.println(cfather);
11     }

 

Console:

 

如图所示:

1.两组对象均不相同,实现了深拷贝

2.第二组的age=0,transient关键字对序列化起了作用。

推荐阅读