是,transient仅影响JVM默认序列化;JSON/XML等需用框架注解如@JsonIgnore或@JSONField(serialize=false)。

transient 修饰的字段真的不会被序列化吗
会,但仅限于默认序列化机制(即 ObjectOutputStream + Serializable 接口)。它只影响 JVM 原生的序列化流程,不作用于 JSON、XML、数据库 ORM 等其他序列化方式。
常见错误现象:transient 字段在用 fastjson 或 jackson 转 JSON 时依然出现,误以为“没生效”——其实根本不是一回事。
使用场景:密码、临时缓存、线程相关对象(如 ThreadLocal)、无法序列化的资源句柄(如 FileInputStream)。
-
transient只能修饰实例变量,不能修饰静态变量或方法 - 反序列化后,
transient字段值为对应类型的默认值(null、0、false) - 若类实现了
writeObject/readObject,需手动跳过该字段,否则可能绕过transient行为
为什么写了 transient 还抛 NotSerializableException
因为字段类型本身不可序列化,且你没把它标成 transient。比如字段是自定义类,该类没实现 Serializable,又没加 transient,序列化时就会炸。
立即学习“Java免费学习笔记(深入)”;
典型错误代码:
public class User implements Serializable {
private String name;
private Connection dbConn; // 没加 transient,Connection 不可序列化
}
修复很简单:
- 加
transient:private transient Connection dbConn; - 或者改用可序列化的替代类型(如只存连接参数字符串)
- 注意:如果该字段被
writeObject手动写入,异常仍会发生
transient 和自定义 writeObject/readObject 怎么配合
当你重写了 writeObject,JVM 就不再自动处理字段,包括跳过 transient 字段——这事得你亲自管。
容易踩的坑:忘了在 writeObject 里跳过 transient 字段,结果敏感数据又被写进字节流。
正确做法示例:
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject(); // 先让 JVM 写非 transient 字段
// 不要写 this.password!它已经是 transient,这里也不该手动写
}
-
defaultWriteObject()自动跳过所有transient字段 - 如果想加密写入某个
transient字段(比如混淆后的密码),必须在defaultWriteObject()之后手动s.writeUTF(...) - 对应地,
readObject中要用defaultReadObject()+ 手动读取匹配顺序
JSON 序列化里 “等效 transient” 的写法有哪些
Java 原生 transient 对 ObjectMapper 或 JSON.toJSONString() 完全无效。要忽略字段,得用框架自己的注解。
常见组合:
- Jackson:
@JsonIgnore(最直接)、@JsonProperty(access = JsonProperty.Access.WRITE_ONLY) - Fastjson:
@JSONField(serialize = false) - Gson:
@Expose(serialize = false, deserialize = false)+ 构造GsonBuilder().excludeFieldsWithoutExposeAnnotation() - 注意:这些注解和
transient无任何关系,别混用或指望它们影响二进制序列化
真正容易被忽略的是:同一个字段,在不同序列化路径下需要不同控制手段。比如既要二进制序列化忽略密码,又要 JSON 输出时忽略,就得同时写 transient 和 @JsonIgnore。










