本文介绍了有效的Java项目#77 - 单例对象的序列化 - 为什么我必须使用readResolve?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#77声明我们必须使用 readResolve 来在序列化期间保留Singleton保证。他们使用了这个例子。

Effective Java #77 states that we have to use readResolve to preserve the Singleton guarentee during serialization. They have used the example.

public class Elvis implements Serializable{
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }

他们建议使用



// readResolve for instance control - you can do better!
private Object readResolve() {
// Return the one true Elvis and let the garbage collector
// take care of the Elvis impersonator.
return INSTANCE; }






  • 现在问题是
    序列化再次加载类
    有两个Elvis实例?

  • 如果类只加载一次
    那么我们应该只有一个
    的Elvis实例,因为静态
    字段没有被序列化并且是
    $ b反序列化期间没有恢复$ b和

  • 其他Elvis
    实例从哪里获得
    可以通过
    获得垃圾回收readResolve(阻止
    转义deserializtaion
    进程)。
    这可以解释一下吗?

  • 推荐答案


    • 该类只加载一次(除非您使用类加载器,但实际上类不同)。上面代码的反序列化确实创建了一个新的 Elvis 。您需要使用串行代理来避免这种情况。

      • The class is only loaded once (unless you muck about with class loaders, but then the classes are actually different). Deserialisation of the above code does indeed create a new Elvis. You would need to use a serial proxy to avoid that.

        虽然有两个 Elvis 实例, Elvis.INSTANCE 仅指向一个。

        Whilst there are two Elvis instances, Elvis.INSTANCE only points to one.

        反序列化构造一个对象而不调用执行任何可序列化的构造函数类(但它执行最派生的非可序列化基类的无参数构造函数)。

        Deserialisation constructs an object without calling executing any constructors of serialisable classes (it does however execute the no-arg constructor of the most derived non-serialisable base class).

        (顺便说一下,你没有把你的班级最终,所以即使是一个子类也可以被反序列化。顺便提一下,你建议的 readResolve 方法,因为它是 private 。)

        (And btw, you've not made your class final, so even a subclass can be deserialised. And, incidentally, your proposed readResolve method would not be called for a subclass as it is private.)

        这篇关于有效的Java项目#77 - 单例对象的序列化 - 为什么我必须使用readResolve?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 13:18