transient关键字用于排除成员变量参与java原生序列化,仅在类实现serializable接口且使用objectoutputstream/objectinputstream时生效;它不作用于json等第三方序列化,也不提供安全加密保障。

transient 关键字不是“隐藏”字段,而是明确告诉 JVM:这个字段不参与默认序列化流程。 它生效的前提是类实现了 Serializable 接口,且使用的是 Java 原生的 ObjectOutputStream/ObjectInputStream 机制。
为什么被 transient 修饰的变量不会被序列化
Java 默认序列化机制在序列化对象时,会遍历所有非 static、非 transient 的实例字段,并将它们的值写入字节流。而 transient 是一个编译期标记,JVM 在生成序列化描述(ObjectStreamClass)时会跳过这些字段:
- JVM 内部通过
ObjectStreamField[]构建可序列化字段列表,默认过滤掉被transient修饰的字段 - 反序列化时,这些字段不会从字节流中读取,而是直接按类型赋予默认值(
null、0、false) - 它不改变字段的访问性,也不影响反射、日志、调试器或内存 dump 中的可见性
它在敏感数据保护中的真实作用和边界
transient 对原生序列化确实能防止密码、token 等字段落入文件或网络字节流中,但它只是“防无意泄露”,不是安全加固手段:
- 对 JSON 序列化(Jackson/Gson)完全无效——除非显式配置
@JsonIgnore或transient感知策略 - 无法阻止代码中主动打印
password、记录到日志、暴露在 HTTP 响应或数据库中 - 如果类重写了
writeObject(),且手动写入了 transient 字段,那它照样会被序列化 - static + transient 组合下,transient 失效(因为 static 本身就不参与序列化)
实际使用中必须配合的措施
单靠 transient 不足以保障敏感数据安全,需叠加以下实践:
- 敏感字段声明为
transient,同时在readObject()中显式校验或清空(如防止反序列化后残留) - 对外输出(JSON/XML/日志)统一走脱敏逻辑,不依赖序列化机制
- 密码类字段优先用
char[]而非String,便于及时Arrays.fill()清理内存 - 涉及传输或存储的敏感数据,必须加密(如 AES 加密后再序列化),而非仅跳过











