transient 是 Java 中的一个字段修饰符,主要用于对象序列化(Serialization)时控制某些字段不被序列化。
transient 的中文翻译是 "瞬态的" 或 "临时的"。
下面从概念、原理、使用场景、示例和注意事项进行系统讲解。
一、什么是 transient
当一个类实现了 Serializable 接口后,对象就可以被序列化(转换为字节流保存或传输)。
如果某个字段使用 transient 修饰,那么:
该字段不会被序列化,也不会被反序列化恢复。
反序列化后,该字段会变成默认值:
引用类型:
null数值类型:
0boolean:
false
二、为什么需要 transient
常见原因:
1. 安全性(最常见)
例如密码不希望被序列化:
class User implements Serializable {
private String username;
private transient String password;
}序列化后,password 不会写入文件或网络。
2. 字段可以重新计算
例如缓存字段:
class Order implements Serializable {
private double price;
private int count;
private transient double totalPrice;
}totalPrice 可以通过
price * count 重新计算。
3. 不可序列化对象
某些对象本身不支持序列化,例如:
private transient Thread thread;
private transient Connection connection;三、基本示例
示例代码
import java.io.*;
class Person implements Serializable {
String name;
transient int age;
Person(String name, int age){
this.name = name;
this.age = age;
}
}
public class Test {
public static void main(String[] args) throws Exception {
Person p = new Person("Tom", 20);
// 序列化
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream("data.txt"));
oos.writeObject(p);
oos.close();
// 反序列化
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("data.txt"));
Person p2 = (Person) ois.readObject();
ois.close();
System.out.println(p2.name); // Tom
System.out.println(p2.age); // 0
}
}输出:
Tom
0因为 age 被 transient 修饰。
四、transient 的底层原理
Java 序列化核心类:
ObjectOutputStream
ObjectInputStream序列化时,JVM 会:
通过反射获取字段
跳过 transient 修饰的字段
写入字节流
即:
transient = 不参与序列化五、transient + 自定义序列化(高级)
即使字段是 transient,仍然可以通过自定义方法手动序列化。
private void writeObject(ObjectOutputStream out) throws Exception {
out.defaultWriteObject();
out.writeInt(age); // 手动写入
}
private void readObject(ObjectInputStream in) throws Exception {
in.defaultReadObject();
age = in.readInt(); // 手动恢复
}这在加密场景很常见。
六、transient 和 static 的区别
很多人容易混淆。
示例:
static int a;
transient int b;两者都不会被序列化,但原因不同。
七、常见面试考点(高频)
1. transient 能修饰哪些?
只能修饰:
成员变量不能修饰:
方法
类
局部变量2. transient 修饰的变量反序列化后一定是 null 吗?
不一定:
基本类型 → 默认值
引用类型 → null
如果自定义 readObject → 可以恢复
3. transient 和 final 一起使用?
可以,但要注意:
transient final int a = 10;反序列化后仍然是 10,因为是常量。
八、真实开发中的典型场景
场景1:密码字段
private transient String password;场景2:缓存字段
private transient Map cache;场景3:数据库连接
private transient Connection conn;九、容易踩坑的点(重要)
Jackson / Fastjson 不完全遵守 transient
例如 JSON 序列化:
Jackson 默认忽略 transient(可配置)
Fastjson 有时不会忽略
如果是接口返回,推荐使用:
@JsonIgnore而不是仅依赖 transient。
十、一句话总结
transient的本质作用:让字段不参与 Java 序列化。
Java transient关键字
https://lautung.com/archives/B6CcmsDu