详解Java序列化和反序列化中的writeReplace方法和readResolve方法
保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/65/ )。
在前面的文章中,我们已经介绍了Java序列化和反序列化中的writeExternal方法和readExternal方法。在进行序列化和反序列化的目标类(可以是继承Serializable接口,也可以是继承Externalizable接口)中,还可以定义两个方法:writeReplace方法和readResolve方法:
Object writeReplace()
:如果一个类中定义了该方法,那对该类的对象进行序列化操作前会先调用该方法。最终该方法返回的对象将被序列化。Object readResolve()
:如果一个类中定义了该方法,那对该类的对象进行反序列操作后会调用该方法。最终该方法返回的对象将作为反序列化的结果。
writeReplace方法和readResolve方法实际上为对象的序列化和反序列化提供了一种“偷梁换柱”的能力:无论实际对象如何,在序列化时都以writeReplace方法的返回值为准;无论序列化数据如何,在反序列化时都以readResolve方法的返回值为准。
我们以writeReplace
方法为例,演示下这种能力。
我们在UserModel03类中定义了writeReplace方法,并在writeReplace方法方法中返回一个全新的对象,如下所示。
public class UserModel03 implements Serializable {
private static final long serialVerisionUID = 123L;
private Integer id;
private String name;
private String description;
// 省略属性的get、set方法
private Object writeReplace() throws ObjectStreamException {
System.out.println("writeReplace doing ...");
UserModel03 userModel = new UserModel03();
userModel.setId(2);
userModel.setName("yeecode");
userModel.setDescription("description from writeReplace");
return userModel;
}
}
然后我们对UserModel03的对象进行序列化和反序列化,如下所示。
private static void demo03() throws Exception {
System.out.println("run demo03:");
UserModel03 userModel03 = new UserModel03();
userModel03.setId(1);
userModel03.setName("易哥");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("m3.tempdata"));
oos.writeObject(userModel03);
oos.flush();
oos.close();
System.out.println("↑write;↓read");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("m3.tempdata"));
UserModel03 newUser = (UserModel03) ois.readObject();
System.out.println("newUser:" + newUser.getId() + "-" + newUser.getName());
System.out.println();
}
最终结果如图所示。
可见,无论实际UserModel03对象如何,最终序列化都是按照writeReplace方法输出的对象展开的。writeReplace方法确实在序列化过程中起到了“偷梁换柱”的效果。
readResolve也有类似的能力,只不过是在反序列化阶段生效。
以上内容均参考《通用源码阅读指导书——MyBatis源码详解》一书。
这是一本以MyBatis的源码为实例讲述源码阅读方法的书籍,并且附带有示例项目源码,MyBatis的全中文注解。书籍还总结了大量的编程知识和架构经验,对提升编程和架构能力十分有用。
书中的“22.3.3 懒加载功能对序列化和反序列化的支持”章节介绍了懒加载中的序列化和反序列化操作,大家可以前往阅读。
在接下来的文章中,我们进一步介绍序列化和反序列化过程中各个方法的执行顺序。
可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。