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

Java transient 關鍵字詳解:序列化過程中的「隱身術」

     編輯:Java 程式設計入門

在 Java 序列化機制中,transient 關鍵字扮演著「守門人」角色:標記字段不參與序列化。本文深入解析其原理、適用場景、注意事項與實戰模式。

核心作用

實現 Serializable 接口的類,默認所有非 static、非 transient 字段會被自動序列化。加上 transient 後:

  • 序列化時:該字段值被忽略,不寫入字節流
  • 反序列化時:該字段恢復為默認值(引用類型 null,基本類型 0/false)
  • 生命週期:僅存在於 JVM 運行時內存中,不持久化到磁盤/網絡

典型應用場景

場景示例字段理由
敏感信息password、token、bankCard、idNumber安全合規,防止數據落盤/傳輸洩露
派生/計算字段fullName(由 firstName+lastName 組合)、totalPrice(由 items 計算)可重新計算,無需持久化,節省空間
非序列化資源引用Thread、Connection、Socket、Logger、Stream這些對象不實現 Serializable,強制序列化會拋異常
緩存/臨時狀態cache、tempBuffer、computedHash運行時重建即可,無需持久化

代碼示例

import java.io.*;

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private String username;
    private transient String password; // 不序列化
    private transient Connection dbConn; // 資源引用,不可序列化
    private String fullName; // 可序列化,或用 transient + 反序列化後重建
    
    // 反序列化後自動調用,重建 transient 字段
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        // 重新建立數據庫連接、計算派生字段等
        this.dbConn = DriverManager.getConnection(URL, USER, PWD);
        this.fullName = this.username + "_restored";
    }
    
    // 序列化前調用,可做敏感數據脫敏
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        // 可在此加密 password 後寫入單獨字段(但通常直接 transient 更簡潔)
    }
}

進階:自定義序列化策略

若需對 transient 字段進行加密存儲或特殊編碼,可實現 private void writeObject(ObjectOutputStream) 與 private void readObject(ObjectInputStream),手動控制寫入/讀取邏輯,而非完全放棄持久化。

常見誤區與注意事項

  1. static 字段本身不序列化:static 屬於類,不屬於對象,transient static 無意義但合法。
  2. final transient 字段:反序列化時無法賦值(final 必須構造器初始化),需配合 readObject 使用 Unsafe 或反射設置,不推薦。
  3. 父類非 Serializable:子類實現 Serializable 但父類未實現,反序列化會調用父類無參構造器初始化父類字段,transient 字段同樣為默認值。
  4. 序列化版本號:務必顯式聲明 serialVersionUID,否則類結構變更導致反序列化失敗(InvalidClassException)。

對比:transient vs Externalizable

特性transient + SerializableExternalizable
控制粒度字段級(排除)對象級(完全手動)
實現複雜度低(默認機制+少量排除)高(需實現 writeExternal/readExternal)
性能一般(反射)高(直接流操作)
適用場景大多數業務對象高性能/特殊格式/大對象

現代替代方案

  • JSON 序列化:Jackson @JsonIgnore、Gson transient 同樣生效,更通用、跨語言。
  • Protobuf/Thrift/Avro:IDL 定義 schema,字段級控制,無需關鍵字。
  • JPA @Transient:持久化層排除字段,與 Java 序列化無關。

總結

transient 是 Java 原生序列化中的「精準屏蔽器」,用於敏感數據保護、資源引用隔離、派生字段優化。掌握其與 static、final、readObject/writeObject 的交互細節,能避免反序列化後的「空指針驚魂」與數據洩露風險。新項目優先考慮 JSON/二進制協議替代原生序列化。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved