详解Java序列化和反序列化中的writeReplace方法和readResolve方法

标签: Java

保留所有版权,请引用而不是转载本文(原文地址 https://yeecode.top/blog/65/ )。

在前面的文章中,我们已经介绍了Java序列化和反序列化中的writeExternal方法和readExternal方法。在进行序列化和反序列化的目标类(可以是继承Serializable接口,也可以是继承Externalizable接口)中,还可以定义两个方法:writeReplace方法和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();
}

最终结果如图所示。

图 22-4 程序运行结果

可见,无论实际UserModel03对象如何,最终序列化都是按照writeReplace方法输出的对象展开的。writeReplace方法确实在序列化过程中起到了“偷梁换柱”的效果。

readResolve也有类似的能力,只不过是在反序列化阶段生效。

以上内容均参考《通用源码阅读指导书——MyBatis源码详解》一书。

通用源码阅读指导书-京东自营

《通用源码阅读指导书》

这是一本以MyBatis的源码为实例讲述源码阅读方法的书籍,并且附带有示例项目源码,MyBatis的全中文注解。书籍还总结了大量的编程知识和架构经验,对提升编程和架构能力十分有用。

书中的“22.3.3 懒加载功能对序列化和反序列化的支持”章节介绍了懒加载中的序列化和反序列化操作,大家可以前往阅读。

在接下来的文章中,我们进一步介绍序列化和反序列化过程中各个方法的执行顺序。

可以访问个人知乎阅读更多文章:易哥(https://www.zhihu.com/people/yeecode),欢迎关注。

作者书籍推荐