Java中直接深复制复杂的对象是相当麻烦的事情,为了简便可以使用Java的对象序列化机制来进行深复制。这个方式需要慎用,因为复制速度会比普通新建实例的复制方式慢很多,而且要求对象必须是实现了Serializable的类型。
public class Test {
public static void main(String args[]) throws IOException, Exception {
TestCopy t1 = new TestCopy("testString");
TestCopy t2 = t1.deepCopy();
System.out.println(t1 == t2);
System.out.println(t1.name);
System.out.println(t2.name);
}
}
class TestCopy implements Serializable {
/**
* 定义了该静态成员变量,类将不会人工计算其指纹
*/
private static final long serialVersionUID = 1L;
public String name;
public TestCopy(String name) {
this.name = name;
}
public TestCopy deepCopy() throws IOException, Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (TestCopy) ois.readObject();
}
}
需要注意的是:
1.序列化机制可以复制对象,即使构造器是私有的;需要特别注意这可能会破坏单例或老式枚举类型对象(Corba 中的枚举)的唯一性。
为解决这个问题,可以在类中添加readResolve方法
class Orientation {
private int value;
public static final Orientation HORIZONTAL = new Orientation(1);
public static final Orientation VERTICAL = new Orientation(2);
private Orientation(int v) {
value = v;
}
protected Object readResolve() {
if (value == 1)
return Orientation.HORIZONTAL;
if (value == 2)
return Orientation.VERTICAL;
return null;
}
}
2.序列化机制面对同一个类的不同版本会分别计算它们的SHA指纹,当相同的时候对象流才可以读入该对象。但是我们可以手动指定类的指纹,即给
private static final long serialVersionUID
赋值。当这个值与之前版本一致时,就可以读入。