readresolve是java反序列化中用于替换反序列化对象的private无参方法,需返回本类实例,常用于单例保护;它在readobject最后阶段执行,仅对java原生序列化生效,返回null则readobject返回null。

在 Java 中,readResolve 是一个特殊的方法,用于在反序列化完成后、对象被返回给调用者之前,**替换即将返回的反序列化对象**。它常用于单例模式保护、对象规范化(如统一使用 canonical 实例)、或防止反序列化绕过构造逻辑。
readResolve 方法的基本要求
readResolve 必须满足以下条件才能被 JVM 识别并调用:
- 方法名必须是
readResolve; - 返回类型必须与当前类兼容(通常是本类或其父类/接口);
- 访问修饰符必须是
private(不能是public或protected); - 不能有参数;
- 定义在待序列化的类中(不是父类,除非父类也显式声明且子类未覆盖)。
典型应用场景:保护单例不被反序列化破坏
即使类实现了 Serializable,若没有 readResolve,反序列化会创建新实例,破坏单例语义:
public class Singleton implements Serializable {
private static final long serialVersionUID = 1L;
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
// 反序列化时,JVM 会在构造出对象后调用此方法
private Object readResolve() {
return INSTANCE; // 返回已有实例,丢弃刚反序列化出来的对象
}
}
这样,无论反序列化多少次,都只返回同一个 INSTANCE。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
注意事项和常见陷阱
仅对“通过 ObjectInputStream.readObject() 反序列化”的对象生效 —— 它不影响 JSON、XML 等其他序列化方式。
-
readResolve在反序列化流程的最后阶段执行(即对象字段已还原完毕,但尚未返回),所以可在其中访问已反序列化的字段值; - 如果返回
null,最终readObject()就返回null(需确保调用方能处理); - 若类继承自可序列化的父类,且父类也定义了
readResolve,子类应显式重写以控制行为; - 与
writeReplace配合使用效果更佳(例如序列化前先替换成代理对象)。
验证是否生效的小技巧
写个简单测试:序列化再反序列化单例对象,比较 == 和 equals:
Singleton s1 = Singleton.getInstance();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s1);
oos.close();
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray())
);
Singleton s2 = (Singleton) ois.readObject();
System.out.println(s1 == s2); // 应输出 true(有 readResolve 时)
没加 readResolve 时,结果是 false。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










