// 序列化
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 標記接口(無方法)。
作用:反序列化時,JVM 比較流中的 UID 與當前類的 UID,不一致拋 InvalidClassException。
private static final long serialVersionUID = 1L;(或固定值)。強烈建議顯式聲明,掌控兼容性策略。// 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,反序列化拋異常,導致數據不可讀。
| 場景 | 策略 | 說明 |
|---|---|---|
| 希望版本兼容 | 保持 UID 不變 | 新增字段/方法不影響反序列化,舊字段保留值,新字段默認值 |
| 不希望兼容(破壞性變更) | 修改 UID | 強制舊數據失效,防止業務邏輯錯誤 |
| 不確定 | 顯式聲明固定值(如 1L) | 避免不同編譯器/JDK 版本產生不同默認 UID |
繼承 Serializable,需實現 writeExternal()/readExternal(),完全自定義序列化格式,性能更高、版本控制更靈活,但開發成本大。
transient 排除序列化(如密碼、臨時緩存)。Externalizable 或成熟框架(Protobuf、Kryo、Jackson)。