transient关键字使被修饰的实例字段在ObjectOutputStream.writeObject()序列化时自动跳过,反序列化后值为默认值;它仅作用于实例字段,对static字段无效,且不提供安全保护。

在 Java 中,ObjectOutputStream 的 writeObject 方法用于序列化对象,而 transient 关键字是控制哪些字段**不参与序列化**的最简单、最直接的方式——它让被修饰的字段在序列化时被自动跳过,反序列化后该字段值为默认值(如 null、0、false)。
transient 字段如何被 writeObject 自动过滤
transient 是 Java 语言级的关键字,作用于字段声明。当 ObjectOutputStream.writeObject() 执行时,JVM 的序列化机制会自动检查每个字段的修饰符,遇到 transient 就直接忽略,不会写入字节流。无需额外代码或重写方法。
- 只对实例字段有效(不能修饰 static 或方法)
- 静态字段(
static)本身就不参与序列化,加transient无意义(编译通过但无效) - 反序列化后,
transient字段值为对应类型的默认值(例如String变成null,int变成0)
基本使用示例:用 transient 控制敏感字段不被序列化
假设有一个用户类,其中密码字段不应被保存到文件或网络传输中:
<font size="2"><pre class="brush:php;toolbar:false;">public class User implements Serializable {<br> private static final long serialVersionUID = 1L;<br> private String name;<br> private transient String password; // 不序列化<br><br> public User(String name, String password) {<br> this.name = name;<br> this.password = password;<br> }<br><br> // getter/setter 略<br>}
序列化后读取:
– name 正常恢复;
– password 为 null(即使原对象中有值)。
立即学习“Java免费学习笔记(深入)”;
注意:transient 不等于安全,只是序列化层面的过滤
transient 仅影响 Java 默认序列化流程,它不提供加密或访问控制,也不防止内存泄露或调试器查看。
- 如果需要真正保护敏感数据,应在业务逻辑中清理(如序列化前设为
null),或使用加密/自定义序列化(writeObject/readObject) - 若需更精细控制(比如某些条件下才忽略某字段),必须配合
private void writeObject(ObjectOutputStream)手动写入字段 - 实现
Externalizable接口时,transient完全失效,所有字段都由你显式控制
替代方案:自定义 writeObject 实现动态过滤
当过滤逻辑不能靠关键字静态决定(比如根据环境、配置或运行时状态跳过字段),可定义私有方法:
<font size="2"><pre class="brush:php;toolbar:false;">private void writeObject(ObjectOutputStream out) throws IOException {<br> out.defaultWriteObject(); // 先写入所有非 transient 字段<br> // 再按需写入/跳过其他内容(如临时计算值、条件性字段)<br> if (!isProduction()) {<br> out.writeObject(this.debugInfo);<br> }<br>}
此时 transient 仍生效(defaultWriteObject() 不写它们),而你可以额外控制是否写入其它内容。


















