序列化反序列化导致单例模式的破坏原因及解决方法 |
您所在的位置:网站首页 › 静态内部类可以序列化吗 › 序列化反序列化导致单例模式的破坏原因及解决方法 |
首先看一下序列化反序列化导致单例模式被破坏的例子: double-check单例 class Singleton implements Serializable { private volatile static Singleton singleton; private Singleton() { } public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }通过序列化再反序列化拿到singleton对比 public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("tempFile")); oos.writeObject(Singleton.getInstance()); File file = new File("tempFile"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); Singleton Singleton = (Singleton) ois.readObject(); System.out.println(Singleton); System.out.println(Singleton.getInstance()); System.out.println(Singleton.getInstance() == Singleton); } }结果 Singleton.Singleton@52cc8049 Singleton.Singleton@6ff3c5b5 false说明反序列化后单例模式被破坏了 破坏的原因要看反序列化的源码了: 反序列化方法readObject()的readObject0()中如果是Object对象则调用readOrdinaryObject(),该方法首先会通过一个三目运算来创建序列化的对象。如果这个对象能实例化就创建一个新对象 obj = desc.isInstantiable() ? desc.newInstance() : null;原因找到了,反序列化回来的对象是新创建的,不是单例的那个了。 解决的办法也在源码中,在通过三目运算创建了对象之后,还会去找这个对象里是否有readResolve()方法,如果有,则通过这方法返回对象。 if (obj != null && handles.lookupException(passHandle) == null && desc.hasReadResolveMethod()){ Object rep = desc.invokeReadResolve(obj); .... }解决办法:在单例对象代码中添加public Object readResolve()方法 class Singleton implements Serializable { private volatile static Singleton singleton; private Singleton() { } public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } public Object readResolve() { return getInstance(); } }这样的执行结果为: Singleton.Singleton@6ff3c5b5 Singleton.Singleton@6ff3c5b5 true是同一个实例了 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |