问题描述
#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 $ c不会为子类调用$ c>方法,因为它是
private
。)(And btw, you've not made your class
final
, so even a subclass can be deserialised. And, incidentally, your proposedreadResolve
method would not be called for a subclass as it isprivate
.)这篇关于有效的Java项目#77 - 单例对象的序列化 - 为什么我必须使用readResolve?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
推荐答案