當父類實作 Serializable 介面時,所有子類**自動獲得序列化能力**,無需額外實作介面或撰寫程式碼。序列化過程會遞迴處理繼承鏈上的所有非暫態、非靜態欄位。
public class SuperC implements Serializable {
int supervalue;
public SuperC(int v) { this.supervalue = v; }
@Override public String toString() { return "supervalue: " + supervalue; }
}
public class SubC extends SuperC { // 未顯式實作 Serializable
int subvalue;
public SubC(int sv, int v) { super(sv); this.subvalue = v; }
@Override public String toString() { return super.toString() + " sub: " + subvalue; }
}
// 測試
SubC obj = new SubC(100, 200);
// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.ser"))) {
oos.writeObject(obj);
}
// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.ser"))) {
SubC restored = (SubC) ois.readObject();
System.out.println(restored); // 輸出: supervalue: 100 sub: 200
}
writeObject/readObject 時,完全由預設機制處理Unsafe.allocateInstance 分配記憶體,再填充欄位。父類若無 Serializable,其建構子會被呼叫(見上篇文章)private static final long serialVersionUID = 1L;,避免類別變更導致 InvalidClassException| 情境 | 父類 | 子類責任 | 關鍵要求 |
|---|---|---|---|
| 父類可序列化 | implements Serializable | 無(自動) | 父類有無參建構子(隱式或顯式) |
| 父類不可序列化 | 未實作 Serializable | 手動序列化父類欄位 | 父類必須有 public/protected 無參建構子 |