java单例模式之readResolve()

1 篇文章 0 订阅
1 篇文章 0 订阅

在我之前的一篇文章中介绍了怎么实现单例模式:
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;
    }
}
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值