您的位置:首页 > 编程语言 > Java开发

java单例模式之readResolve()

2016-03-25 17:49 531 查看
在我之前的一篇文章中介绍了怎么实现单例模式:

/article/7874730.html

但是,这是存在问题的。

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

序列化,反序列化!

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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: