transient关键字仅在Java原生序列化(ObjectOutputStream/ObjectInputStream)中生效,用于跳过字段序列化;对JSON、日志、数据库等无效,反序列化后该字段恢复为默认值(null/0/false)。

transient 关键字只能在 Java 原生序列化(ObjectOutputStream/ObjectInputStream)中跳过字段,它不是通用过滤机制,对 JSON、日志、数据库等完全无效。
什么时候加 transient 才真正起作用
只有以下场景下,transient 才会实际阻止字段写入字节流:
- 用
ObjectOutputStream把对象写入文件或 socket(如老式 RMI、定制 RPC) - 使用基于
Serializable的缓存方案(如 Ehcache 2.x 默认配置) - Spring Session 启用了过时的
DefaultCookieSerializer且未禁用序列化
怎么正确声明 transient 字段
只需在实例变量前加上 transient,并确保类实现 Serializable 接口:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- ✅ 正确:
private transient String password; - ❌ 无效:
private static transient String password;(static 本就不序列化) - ❌ 不推荐:
public transient String password;(破坏封装性) - ⚠️ 注意:反序列化后该字段为默认值(
null、0、false),不会自动恢复
为什么加了 transient 还在日志或 API 响应里看到密码
因为日志打印的是内存实时值,JSON 库(如 Jackson)默认不识别 transient:
立即学习“Java免费学习笔记(深入)”;
-
logger.info("user: {}", user)触发toString(),若方法里拼了password,就会直接输出 - Spring Boot 的
@ResponseBody走 Jackson,默认忽略 transient - 解决方式不是依赖 transient,而是改输出逻辑:重写
toString()、用@ToString(exclude = "password")(Lombok)、或 JSON 场景显式加@JsonIgnore
比 transient 更可靠的做法
现代系统应避免把敏感字段暴露在可序列化类中:
- 数据库实体与 API 响应体严格分离,用专用 DTO(如
UserResponse),里面根本不声明password - 敏感字段类型改用
char[],使用后立即调用Arrays.fill(pwd, '\0')清空 - CI 流程中用 SpotBugs 检查
SE_BAD_FIELD,自动发现漏保护的敏感字段 - 必须自定义序列化时,配合
transient+writeObject(),只写脱敏摘要或跳过写入

















