transient关键字用于标记字段不参与序列化,反序列化后为默认值;适用于敏感信息、临时数据、不可序列化资源等场景,仅修饰实例变量,可配合writeobject/readobject自定义逻辑。

在 Java 中,transient 关键字用于标记某个字段**不参与序列化过程**。当一个类实现了 Serializable 接口,Java 默认会将所有非静态、非瞬态(non-transient)的实例变量保存到字节流中;而被 transient 修饰的字段,在序列化时会被跳过,反序列化后其值为对应类型的默认值(如 null、0、false)。
哪些场景适合用 transient?
常见于以下情况:
- 敏感信息(如密码、密钥),不应随对象一起持久化或网络传输
- 临时计算结果或缓存数据,无需保存,反序列化后可重新生成
- 与序列化上下文无关的对象(如线程、Socket、数据库连接等不可序列化的资源)
- 避免因字段类型不可序列化导致整个对象无法序列化(比如字段是自定义类但未实现
Serializable)
基本用法和注意事项
只需在字段声明前加上 transient 即可:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private transient String password; // 不序列化
private transient int loginCount; // 反序列化后为 0
}
注意:
-
transient只能修饰实例变量,不能修饰方法、类或局部变量 -
static字段本身就不参与序列化,加transient无意义(编译通过但无效) - 若需对
transient字段做自定义序列化逻辑(如加密保存、延迟初始化),可配合writeObject和readObject方法
配合自定义序列化控制行为
如果希望在反序列化后恢复 transient 字段的值(比如从配置重载、重新计算),可手动实现:
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject(); // 先序列化其他字段
out.writeUTF(encrypt(password)); // 自定义写入加密后的密码
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); // 先反序列化其他字段
this.password = decrypt(in.readUTF()); // 手动恢复 password
}
这样既避开自动序列化敏感字段,又保留了反序列化后的可用性。
常见误区提醒
容易混淆的点:
-
transient不等于volatile或final,它只影响序列化,不影响并发或赋值约束 - 子类继承父类字段时,若父类字段被
transient修饰,子类序列化时依然不会保存该字段 - 使用 JSON 库(如 Jackson、Gson)时,
transient默认也生效(但可通过注解覆盖,如@JsonProperty)
不复杂但容易忽略:只要字段不该随对象“带走”,就值得考虑加 transient —— 安全性和序列化健壮性往往就藏在这种小细节里。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











