ObjectOutputStream.putFields 是用于显式控制序列化字段值的高级API,需在 private void writeObject(ObjectOutputStream) 中调用,支持对 transient 字段强制写入、动态计算值等场景,但不可与 defaultWriteObject 混用。

ObjectOutputStream.putFields 是 Java 序列化机制中用于**显式控制字段写入内容**的高级 API,适用于需要在序列化时动态计算、转换或屏蔽字段值的场景(比如加密字段、忽略 transient 但需写入默认值、兼容旧版本数据格式等)。它不替代常规序列化,而是配合 writeFields() 使用,在自定义 writeObject() 方法中生效。
必须重写 writeObject() 方法
putFields 仅在类声明了自定义 private void writeObject(ObjectOutputStream out) 且其中调用 out.putFields() 时才起作用。若未提供该方法,序列化仍走默认流程,putFields 不会被触发。
- 方法签名必须严格为
private void writeObject(ObjectOutputStream out) throws IOException - 不能是
protected或public,也不能带额外参数 - 需在方法内先调用
out.putFields()获取PutField实例,再设置字段值,最后调用out.writeFields()
使用 PutField 设置字段值
通过 putFields() 返回的 ObjectOutputStream.PutField 对象,可对当前对象的**所有可访问字段(包括 private)** 赋值,即使字段是 transient 或 static —— 但注意:static 字段不会被序列化,此处设值无效;transient 字段则可通过此方式强制写入。
-
put(String name, boolean value)/put(String name, int value)等重载方法写入基本类型或 String - 字段名必须与类中声明的字段名完全一致(区分大小写)
- 未显式
put的字段,在writeFields()时会写入其当前内存值(即默认行为),不是 null 或 0 - 若字段不存在,运行时抛
IllegalArgumentException
典型使用场景示例
例如,某用户类含敏感字段 password(transient),但需序列化为哈希值而非明文:
立即学习“Java免费学习笔记(深入)”;
private void writeObject(ObjectOutputStream out) throws IOException {
ObjectOutputStream.PutField fields = out.putFields();
// 写入加工后的 password(如哈希)
fields.put("password", hashPassword(this.password));
// 显式写入其他字段(也可不 put,保持原值)
fields.put("username", this.username);
fields.put("age", this.age);
out.writeFields(); // 必须调用,真正触发写入
}注意:此时 password 即使是 transient,也会被写入;而未调用 put 的字段(如遗漏 username)将按反射获取的当前值写入。
与 defaultWriteObject 的区别
putFields 是“白名单式”显式控制,适合精细定制;而 defaultWriteObject() 是“黑名单式”默认写入(跳过 transient 和 static)。两者不可混用在同一 writeObject 中 —— 若调用了 putFields(),就必须用 writeFields() 提交,不能再调 defaultWriteObject(),否则抛 IOException。


















