首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2SE

Java 序列化基礎:父類實作 Serializable 時的子類自動序列化機制

     編輯:J2SE

核心規則

當父類實作 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
}

運作原理

  • JVM 序列化時,從最頂層可序列化的父類開始,依序寫入各層級欄位
  • 反序列化時,先呼叫最頂層非序列化父類的無參建構子(若有),再依序恢復各層欄位
  • 子類不覆寫 writeObject/readObject 時,完全由預設機制處理

常見誤區與注意事項

  1. 父類建構子呼叫時機:反序列化**不會**呼叫子類建構子,而是透過 Unsafe.allocateInstance 分配記憶體,再填充欄位。父類若無 Serializable,其建構子會被呼叫(見上篇文章)
  2. transient 關鍵字:標記不需序列化的欄位,反序列化後為預設值(null/0/false)
  3. static 欄位:屬於類別而非實例,**不參與序列化**
  4. serialVersionUID:強烈建議顯式宣告 private static final long serialVersionUID = 1L;,避免類別變更導致 InvalidClassException

設計建議

  • 若類別設計為可被繼承的基底類,**預設實作 Serializable**,除非有強烈理由不序列化(如持有非序列化資源)
  • 文件化序列化形式:哪些欄位會被序列化、版本相容性政策
  • 單元測試驗證:序列化→修改類別(增欄位)→反序列化,確認向後相容

對比總結:兩種繼承情境

情境父類子類責任關鍵要求
父類可序列化implements Serializable無(自動)父類有無參建構子(隱式或顯式)
父類不可序列化未實作 Serializable手動序列化父類欄位父類必須有 public/protected 無參建構子
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved