java单例模式之readResolve()
2016-03-25 17:49
531 查看
在我之前的一篇文章中介绍了怎么实现单例模式:
/article/7874730.html
但是,这是存在问题的。
不考虑反射这种极端情况,还有一种情况会破坏单例模式。
序列化,反序列化!
测试代码:
结果:
问题来了,怎么解决呢?jdk其实预料到这种情况了。
解决方法:加入readResolve()
在jdk中ObjectInputStream的类中有readUnshared()方法,上面详细解释了原因。我简单描述一下,那就是如果被反序列化的对象的类存在readResolve这个方法,他会调用这个方法来返回一个“array”(我也不明白),然后浅拷贝一份,作为返回值,并且无视掉反序列化的值,即使那个字节码已经被解析。
所以,完整的单例模式是:
/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; } }
相关文章推荐
- JavaWeb项目开发案例精粹-第3章在线考试系统-007View层
- java 读入换行
- Java中OutOfMemoryError(内存溢出)的三种情况及解决办法
- 用Java实现各种排序(1)---冒泡排序,直接插入排序,简单选择排序
- java输入输出的理解和掌握
- Java中的字符串常量池
- spring-boot 所有的配置
- JavaWeb项目开发案例精粹-第3章在线考试系统-006实体层
- JavaWeb项目开发案例精粹-第3章在线考试系统-005action层
- java并发编程synchronized、volatile关键字及ReentrantLock类总结
- Spring mvc+hibernate+freemarker(开源项目)
- JavaWeb项目开发案例精粹-第3章在线考试系统-004Service层
- 本体学习笔记--在eclipse里操作本体的准备
- JavaWeb项目开发案例精粹-第3章在线考试系统-003Dao层
- Java 学习系列:LinkedList 的实现原理
- 理解Java虚拟机体系结构
- JavaWeb项目开发案例精粹-第3章在线考试系统-002配置文件及辅助类
- (补)环境变量的配置以及eclipse的快捷键
- java多线程小结,及解决应用挂死的问题
- 分析JAVA应用CPU占用过高的问题