java单例模式之readResolve()

版权声明:欢迎访问个人博客网站 www.dubby.cn,和个人微信公众号ITBusTech https://blog.csdn.net/u011499747/article/details/50982956

在我之前的一篇文章中介绍了怎么实现单例模式:
http://blog.csdn.net/u011499747/article/details/48194431
但是,这是存在问题的。

不考虑反射这种极端情况,还有一种情况会破坏单例模式。
序列化,反序列化!

package cp2;

import java.io.Serializable;
import java.util.Objects;

/**
 * Created by dubby on 16/3/25.
 */
public class SerSingleton implements Serializable {
    String name;
    private SerSingleton(){
        System.out.println("Singleton is creating");
    }

    private static SerSingleton instance = new SerSingleton();

    public static SerSingleton getInstance(){
        return instance;
    }

    public static void createString(){
        System.out.println("create string in singleton");
    }
}

测试代码:

import cp2.SerSingleton;
import junit.framework.Assert;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * Created by dubby on 16/3/25.
 */
public class SerSingletonTest {

    @Test
    public void test() throws Exception{
        SerSingleton s1 = null;
        SerSingleton s = SerSingleton.getInstance();

        FileOutputStream fos = new FileOutputStream("a.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(s);
        oos.flush();
        oos.close();

        FileInputStream fis = new FileInputStream("a.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        s1 = (SerSingleton) ois.readObject();

        Assert.assertEquals(s,s1);
    }
}

结果:

junit.framework.AssertionFailedError: 
Expected :cp2.SerSingleton@7ab2bfe1
Actual   :cp2.SerSingleton@497470ed
   <Click to see difference>

问题来了,怎么解决呢?jdk其实预料到这种情况了。
解决方法:加入readResolve()

在jdk中ObjectInputStream的类中有readUnshared()方法,上面详细解释了原因。我简单描述一下,那就是如果被反序列化的对象的类存在readResolve这个方法,他会调用这个方法来返回一个“array”(我也不明白),然后浅拷贝一份,作为返回值,并且无视掉反序列化的值,即使那个字节码已经被解析。
所以,完整的单例模式是:

package cp2;

import java.io.Serializable;
import java.util.Objects;

/**
 * Created by dubby on 16/3/25.
 */
public class SerSingleton implements Serializable {
    String name;
    private SerSingleton(){
        System.out.println("Singleton is creating");
    }

    private static SerSingleton instance = new SerSingleton();

    public static SerSingleton getInstance(){
        return instance;
    }

    public static void createString(){
        System.out.println("create string in singleton");
    }

    private Object readResolve(){
        System.out.println("read resolve");
        return instance;
    }
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页