若需對整個物件進行加密與簽名,最簡單方式是使用 javax.crypto.SealedObject 與 java.security.SignedObject 包裝器。兩者皆實作 Serializable,可將原物件包裝成「密封盒」:
組合使用可輕鬆實現序列化資料的機密性與完整性,無需手動處理加密/簽名細節。
當類別包含核心資料欄位,可由此推導其他欄位時,無需序列化完整物件。可將欄位標記 transient,但每次存取仍需檢查初始化。更好的方式是指定 Flyweight 或 代理 物件寫入序列化流:
writeReplace():序列化時回傳代理物件替換原物件。readResolve():反序列化時由代理物件還原真實物件。class PersonProxy implements java.io.Serializable {
public PersonProxy(Person orig) {
data = orig.getFirstName() + "," + orig.getLastName() + "," + orig.getAge();
if (orig.getSpouse() != null) {
Person spouse = orig.getSpouse();
data += "," + spouse.getFirstName() + "," + spouse.getLastName() + "," + spouse.getAge();
}
}
public String data;
private Object readResolve() throws java.io.ObjectStreamException {
String[] pieces = data.split(",");
Person result = new Person(pieces[0], pieces[1], Integer.parseInt(pieces[2]));
if (pieces.length > 3) {
result.setSpouse(new Person(pieces[3], pieces[4], Integer.parseInt(pieces[5])));
result.getSpouse().setSpouse(result);
}
return result;
}
}
public class Person implements java.io.Serializable {
// ... 建構子、getter/setter ...
private Object writeReplace() throws java.io.ObjectStreamException {
return new PersonProxy(this); // 序列化時替換為代理
}
private String firstName, lastName;
private int age;
private Person spouse;
}
此模式大幅減少序列化體積,並可隱藏敏感欄位或簡化物件圖結構。
反序列化後不應盲目信任資料完整性。實作 ObjectInputValidation 介面並覆寫 validateObject(),發現欄位值異常時拋出 InvalidObjectException,確保資料一致性(「以防萬一」的防禦性程式設計)。