单例设计模式-序列化破坏单例模式?
1、问题猜想,假如将一个对象通过序列化放到一个文件后,再取出来看是否与本身相等?
public class HungrySingleton implements Serializable { private final static HungrySingleton hungrySingleton; static { hungrySingleton = new HungrySingleton(); } private HungrySingleton() { } public static HungrySingleton getInstance() { return hungrySingleton; } }
public class Test { public static void main(String[] args) throws IOException, ClassNotFoundException { HungrySingleton instance = HungrySingleton.getInstance(); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("single_file")); oos.writeObject(instance); File file = new File("single_file"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); HungrySingleton newInstance = (HungrySingleton) ois.readObject(); System.out.println(instance); System.out.println(newInstance); System.out.println(instance == newInstance); } }
结果:
com.wenwen.design.pattern.Creational.singleton.HungrySingleton@45ee12a7 com.wenwen.design.pattern.Creational.singleton.HungrySingleton@7699a589 false
由此可见,instance和newInstance不相等,就违背了单例模式的一个初衷,通过序列化和反序列化拿到了不同的对象。而我们是希望拿到一个对象。
那么如何解决呢?
在单例中加一个方法就可解决,如下代码所示:
public class HungrySingleton implements Serializable { private final static HungrySingleton hungrySingleton; static { hungrySingleton = new HungrySingleton(); } private HungrySingleton() { } public static HungrySingleton getInstance() { return hungrySingleton; } private Object readResolve() { return hungrySingleton; } }
再次运行测试类之后,结果如下:
com.wenwen.design.pattern.Creational.singleton.HungrySingleton@45ee12a7 com.wenwen.design.pattern.Creational.singleton.HungrySingleton@45ee12a7 true
为什么如此神奇呢?这就要大家深入看下源码了。按command+enter进行该处的源码。
因为使用了序列化,则会new一个新的实例,所以前面看到会返回两个不同的实例。
因为代码里写了readResolve()方法,会反射出原先的实例进行返回,则写了readResolve()方法之后,会返回同一个实例。
想要飞得更高,就该忘记地平线!