transient关键字用于Java中表示应当 排除在序列化过程中 的类字段——即,这些字段在将对象保存到字节流时不会被保存。
这在以下情况下很有用:
使用示例:
import java.io.*; class User implements Serializable { private String username; private transient String password; // 不会被序列化 public User(String username, String password) { this.username = username; this.password = password; } }
在反序列化后,password字段将为 null。
如果transient字段是对一个实现了Serializable的对象的引用,会发生什么?
回答:字段仍然不会被序列化——这适用于字段,而不是对象的类型。即使对象实现了Serializable,如果字段被标记为transient,它在序列化时也不会被包含在该对象中。
示例:
class Credentials implements Serializable { String password; } class Account implements Serializable { transient Credentials credentials; }
字段 credentials 在反序列化后始终为null,即使Credentials本身是可序列化的。
故事
在互联网银行中,设计"用户会话"对象时,忘记将授权会话字段声明为transient,导致序列化的对象与机密信息一起记录到文件中。这导致了个人数据泄露。
故事
在经纪服务中,某些缓存字段默认被序列化。恢复序列化状态后,应用程序开始使用过时的缓存数据,导致实际和显示的帐户金额之间出现不一致。
故事
开发人员实现了transient字段,认为该值在反序列化后会自动填充。他没有实现自定义的readObject/writeObject结构,结果字段保持为null——程序在首次访问该字段时崩溃。