Map,List,POJO深拷贝(序列化实现)方法与注意事项

时间:2023-04-07 15:14:26

转载请注明出处,谢谢!

方法1:

   /*jdk >= 1.5*/
@SuppressWarnings("unchecked")
public static <T> T deepClone(T obj) {
T clonedObj = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
ByteArrayInputStream bais = new ByteArrayInputStream(
baos.toByteArray());
ois = new ObjectInputStream(bais);
clonedObj = (T) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
oos.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
} }
return clonedObj;
}

方法2:

    /*jdk >= 1.7*/
@SuppressWarnings("unchecked")
public static <T> T deepCopy(T srcObj) {
T targetObj = null;
try
(
ByteArrayInputStream bais = new ByteArrayInputStream(deepCopyRepo(srcObj, new ByteArrayOutputStream()).toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais)
)
{
targetObj = (T) ois.readObject();
}
catch (Exception e)
{
e.printStackTrace();
}
return targetObj;
}
public static ByteArrayOutputStream deepCopyRepo(Object obj,ByteArrayOutputStream baos) throws Exception {
try
(
ObjectOutputStream oos = new ObjectOutputStream(baos)
)
{
oos.writeObject(obj);
}
return baos;
}

注意事项:

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:

 import java.io.Serializable;
import java.util.List; public class Person implements Serializable{
/*自定义版本*/
private static final long serialVersionUID = 1L; private String name;
private List<Person> children;
/*age属性因transient修饰,所以被序列化机制隔离*/
private transient int age;
public Person(String name,List<Person> children,int age){
this.name = name;
this.children = children;
this.age = age;
}
public Person(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Person> getChildren() {
return children;
}
public void setChildren(List<Person> children) {
this.children = children;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override/*根据jvm返回的hashCode判断对象相同*/
public String toString() {
return "Person"+ "@" + Integer.toHexString(this.hashCode())+" [name=" + name + ", children=" + children + ", age="
+ age + "]";
}
}

junit:

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

Console:

Map,List,POJO深拷贝(序列化实现)方法与注意事项

如图所示:

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

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