transient仅对Java原生序列化有效,使字段不被ObjectOutputStream写入;反序列化后字符串为null、基本类型为默认值;需实现Serializable接口并建议显式定义serialVersionUID;对JSON等序列化无效,须配合@JsonIgnore等注解或DTO隔离敏感数据。
transient 关键字能跳过 Java 原生序列化过程,让密码等字段不写入磁盘文件或网络字节流,但仅限于
/
场景。
它怎么起作用
只要字段被
修饰,JVM 在调用
时就会自动忽略该字段——既不保存值,也不在反序列化时恢复。例如:
字符串类型(如
)反序列化后为
基本类型(如
)反序列化后为
或
它不加密、不删数据,只是“不拷贝”,内存里依然存在,日志、调试器、堆转储照常可见
必须配合 Serializable 接口使用
transient 单独声明无效,类必须实现
,且通常建议显式定义
:
没写
时,JVM 会基于非-static、非-transient 字段自动生成;加了
后,UID 值一般不变
但若后续增删了非-transient 字段,务必重新生成并更新
,否则跨版本反序列化可能失败
它防不住 JSON、HTTP 响应这些常见场景
Spring Boot 的
、Feign 调用、前端 AJAX 请求,底层多用 Jackson 序列化 JSON——而
默认对 Jackson 完全无效:
Jackson 需额外开启:
更推荐直接用注解:
(Jackson)、
(Fastjson)、
(Gson)
别指望一个
同时管住二进制流和 JSON,这是两个独立机制
真正安全的做法不是只靠 transient
把敏感字段标为
是基础动作,但生产环境还需叠加其他控制:
用 DTO 对象返回响应,比如
里根本不声明
字段
数据库查出的实体(含密码)绝不直接返回给前端,必须转换
密码字段在入库前应哈希加盐,内存中也不宜长期保留明文
若需自定义序列化逻辑(如只存密码摘要),可结合
+
手动控制
ObjectOutputStreamObjectInputStreamtransientwriteObject()private transient String password;nullprivate transient int attempts;0falseSerializableserialVersionUIDserialVersionUIDtransientserialVersionUID@ResponseBodytransientmapper.configure(MapperFeature.USE_TRANSIENT_ANNOTATION, true)@JsonIgnore@JSONField(serialize = false)@Expose(serialize = false)transienttransientUserDTOpasswordtransientprivate void writeObject()