当我们查看 Object 中的clone() 方法的API时发现有这样一段话:‘......this method performs a "shallow copy" of this object, not a "deep copy" operation....’
事实确实这样,是一个复杂对象该方式是无法实现clone的。 仔细看下会发现该方法 使用‘protected’修饰的,这样造成的后果就是:对那些简单地使用一下这个类的客户程序员来说,他们不会默认地拥有这个方法;其次,我们不能利用指向基础类的一个句柄来调用clone()(尽管那样做在某些情况下特别有用,比如用多形性的方式克隆一系列对象)。
那么我们如何实现深度copy呢??
上代码前先看看 ObjectOutputStream 的 writeObject(Object obj) 和
ObjectInputStream 的 readObject() 方法的API
方法writeObject(Object obj):
/**
* Write the specified object to the ObjectOutputStream. The class of the
* object, the signature of the class, and the values of the non-transient
* and non-static fields of the class and all of its supertypes are
* written. Default serialization for a class can be overridden using the
* writeObject and the readObject methods. Objects referenced by this
* object are written transitively so that a complete equivalent graph of
* objects can be reconstructed by an ObjectInputStream.
*...............................
方法readObject():
Objects referenced by this object are read transitively so that a complete equivalent graph of objects is reconstructed by readObject.
代码还是最能说明问题的:
package com.test.clone;
import java.io.Serializable;
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
private int age;
private String name;
public Person(){};
public Person(int age,String name){
this.age=age;
this.name=name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected final Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
public static void main(String[] args) {
Person person = new Person();
//person.clone();
}
}
-------------------------------------------------------------------------------------
package com.test.clone;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
public class PersonDeepCopyTest {
public static <T> void printList(List<T> list){
System.out.println("---begin---");
for(T t : list){
System.out.println(t);
}
System.out.println("---end---");
}
public static <T> void printArray(T[] array){
System.out.println("---begin---");
for(T t : array){
System.out.println(t);
}
System.out.println("---end---");
}
/**
* 深度copylist
* @param <T>
* @param src
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(src);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
@SuppressWarnings("unchecked")
List<T> dest = (List<T>) in.readObject();
return dest;
}
/**
*
* @param <G>
* @param src
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static <G> List<G> deep4Copy(List<G> src) throws IOException, ClassNotFoundException{
ByteArrayOutputStream byteout= new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteout);
out.writeObject(src);
ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bytein);
List<G> dest = (List<G>) in.readObject();
return dest;
}
/**
* 深度copyMap
* @param <G>
* @param <E>
* @param src
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static <G,E> Map<G,E> deep4MapCopy(Map<G,E> src) throws IOException, ClassNotFoundException{
ByteArrayOutputStream byteout= new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteout);
out.writeObject(src);
ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bytein);
Map<G,E> dest = (Map<G,E>) in.readObject();
return dest;
}
/**
* 深度copy Hashtable
* @param <G>
* @param <E>
* @param src
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static <G,E> Hashtable<G,E> deep4HashTableCopy(Hashtable<G,E> src) throws IOException, ClassNotFoundException{
ByteArrayOutputStream byteout= new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteout);
out.writeObject(src);
ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bytein);
Hashtable<G,E> dest = (Hashtable<G,E>) in.readObject();
return dest;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
List<Person> srcList=new ArrayList<Person>();
Person p1=new Person(20,"123");
Person p2=new Person(21,"ABC");
Person p3=new Person(22,"abc");
srcList.add(p1);
srcList.add(p2);
srcList.add(p3);
/* List<Person> destList=new ArrayList<Person>(srcList.size());
for(Person p : srcList){
destList.add(p); //无法实现深度copy
}
printList(destList);
srcList.get(0).setAge(100);
printList(destList);
printList(srcList);*/
/* List<Person> destList=new ArrayList<Person>();
destList.addAll(srcList); //无法实现深度copy
printList(destList);
srcList.get(0).setAge(100);
printList(destList);
printList(srcList);*/
List<Person> destList=deepCopy(srcList); //可实现List深度copy
printList(destList);
destList.get(0).setAge(100);
printList(destList);
printList(srcList);
/* Map<String,Person> srcMap=new HashMap<String,Person>();
Person p1=new Person(20,"123");
Person p2=new Person(21,"ABC");
Person p3=new Person(22,"abc");
srcMap.put(p1.getName(),p1);
srcMap.put(p2.getName(),p2);
srcMap.put(p3.getName(),p3);
Map<String, Person> destMap = deep4MapCopy(srcMap);//可实现Map深度copy
System.out.println(destMap);
destMap.get("abc").setAge(100);
System.out.println(destMap);
System.out.println(srcMap);*/
/* Hashtable<String,Person> srcHashTable=new Hashtable<String,Person>();
Person p1=new Person(20,"123");
Person p2=new Person(21,"ABC");
Person p3=new Person(22,"abc");
srcHashTable.put(p1.getName(),p1);
srcHashTable.put(p2.getName(),p2);
srcHashTable.put(p3.getName(),p3);
Map<String, Person> desthashtable = deep4HashTableCopy(srcHashTable);//可实现List深度copy
System.out.println(desthashtable);
desthashtable.get("abc").setAge(100);
System.out.println(desthashtable);
System.out.println(srcHashTable);*/
}
}