對象序列化後再反序列化,實質經歷一個「複製」過程。為何不直接用序列化做深層複製?以下程式碼對比兩種方法效能:
//: Compete.java
import java.io.*;
class Thing1 implements Serializable {}
class Thing2 implements Serializable { Thing1 o1 = new Thing1(); }
class Thing3 implements Cloneable {
public Object clone() {
Object o = null;
try { o = super.clone(); }
catch (CloneNotSupportedException e) { System.out.println("Thing3 can't clone"); }
return o;
}
}
class Thing4 implements Cloneable {
Thing3 o3 = new Thing3();
public Object clone() {
Thing4 o = null;
try { o = (Thing4)super.clone(); }
catch (CloneNotSupportedException e) { System.out.println("Thing4 can't clone"); }
o.o3 = (Thing3)o3.clone(); // 深層複製欄位
return o;
}
}
public class Compete {
static final int SIZE = 5000;
public static void main(String[] args) {
Thing2[] a = new Thing2[SIZE];
for(int i = 0; i < a.length; i++) a[i] = new Thing2();
Thing4[] b = new Thing4[SIZE];
for(int i = 0; i < b.length; i++) b[i] = new Thing4();
try {
// 序列化複製
long t1 = System.currentTimeMillis();
ByteArrayOutputStream buf = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(buf);
for(int i = 0; i < a.length; i++) o.writeObject(a[i]);
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(buf.toByteArray()));
Thing2[] c = new Thing2[SIZE];
for(int i = 0; i < c.length; i++) c[i] = (Thing2)in.readObject();
long t2 = System.currentTimeMillis();
System.out.println("Duplication via serialization: " + (t2 - t1) + " Milliseconds");
// Clone 複製
t1 = System.currentTimeMillis();
Thing4[] d = new Thing4[SIZE];
for(int i = 0; i < d.length; i++) d[i] = (Thing4)b[i].clone();
t2 = System.currentTimeMillis();
System.out.println("Duplication via cloning: " + (t2 - t1) + " Milliseconds");
} catch(Exception e) { e.printStackTrace(); }
}
} ///:~
Thing2/Thing4 含成員物件,需深層複製。序列化設定簡單但複製耗時;Clone 類別設定繁瑣但實際複製極快。
Duplication via serialization: 3400 Milliseconds Duplication via cloning: 110 Milliseconds Duplication via serialization: 3410 Milliseconds Duplication via cloning: 110 Milliseconds Duplication via serialization: 3520 Milliseconds Duplication via cloning: 110 Milliseconds
序列化比 Clone 慢 30 倍以上,且時間波動大;Clone 每次耗時穩定。除非極度重視開發便利性,效能敏感場合首選 clone()。