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

Java 序列化與反序列化深度指南:serialVersionUID 核心機制與版本演進

     編輯:Java 綜合教學

Java 序列化與反序列化深度指南:serialVersionUID 核心機制與版本演進

核心概念

  • 序列化:對象 → 字節序列(持久化到磁盤/網絡傳輸)。
  • 反序列化:字節序列 → 對象(還原到內存)。
  • 主要用途:Session 持久化、RPC 參數傳遞、分布式對象共享。

JDK 序列化 API

// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"));
oos.writeObject(user);
oos.close();

// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"));
User user = (User) ois.readObject();
ois.close();

前提:類實現 Serializable 標記接口(無方法)。

serialVersionUID:版本兼容性的守門員

作用:反序列化時,JVM 比較流中的 UID 與當前類的 UID,不一致拋 InvalidClassException。

兩種生成方式

  1. 默認算法:基於類結構(類名、接口、字段、方法簽名)生成 64 位哈希。類結構微變(增刪字段/方法、修改修飾符)UID 皆變。
  2. 顯式聲明:private static final long serialVersionUID = 1L;(或固定值)。強烈建議顯式聲明,掌控兼容性策略。

實戰演示:字段演進與 UID 控制

// V1
class Customer implements Serializable {
    private static final long serialVersionUID = -5182532647273106745L; // 固定
    private String name;
    private int age;
}

// 序列化存盤

// V2 新增 sex 字段
class Customer implements Serializable {
    private static final long serialVersionUID = -5182532647273106745L; // 保持不變
    private String name;
    private int age;
    private String sex; // 新增
}

結果:反序列化成功,sex 為 null(默認值),老數據平滑遷移。

若未固定 UID,V2 編譯生成新 UID,反序列化拋異常,導致數據不可讀。

serialVersionUID 取值策略

場景策略說明
希望版本兼容保持 UID 不變新增字段/方法不影響反序列化,舊字段保留值,新字段默認值
不希望兼容(破壞性變更)修改 UID強制舊數據失效,防止業務邏輯錯誤
不確定顯式聲明固定值(如 1L)避免不同編譯器/JDK 版本產生不同默認 UID

進階:Externalizable 接口

繼承 Serializable,需實現 writeExternal()/readExternal(),完全自定義序列化格式,性能更高、版本控制更靈活,但開發成本大。

最佳實踐清單

  1. 所有可序列化類顯式聲明 serialVersionUID。
  2. 新增字段保持 UID 不變;刪除字段、修改類型屬破壞性變更,需評估兼容性。
  3. 敏感字段用 transient 排除序列化(如密碼、臨時緩存)。
  4. 大對象圖考慮 Externalizable 或成熟框架(Protobuf、Kryo、Jackson)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved