一个单例对象创建好后,有时候需要将对象序列化然后写进磁盘,下次使用时再从磁盘中读取对象并进行反序列化,将其转换为内存对象,反序列化后的对象会重新分配内存,即重新创建。如果序列化的目标为单列对象,就会破坏单例模式。
public class SerialSingleton implements Serializable {
public final static SerialSingleton INSTANCE = new SerialSingleton();
private SerialSingleton() {}
public static SerialSingleton getInstance() { return INSTANCE; }
}
/** 测试类*/
public class SerialSingletonTest {
public static void main(String[] args) {
SerialSingleton s1 = null;
SerialSingleton s2 = SerialSingleton.getInstance();
FileOutputStream fos = null;
try {
fos = new FileOutputStream("SerialSingleton.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s2);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("SerialSingleton.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
s1 = (SerialSingleton) ois.readObject();
ois.close();
System.out.println(s1);
System.out.println(s2);
System.out.println(s1 == s2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
com.singleton.seriable.SerialSingleton@6e3c1e69
com.singleton.seriable.SerialSingleton@7b3300e5
false
显然,序列化会破坏单例.....emm那要怎么办,这时候有一个叫readResolve()的方法出现了。就很神奇,把他放在SerialSingleton类中,再次运行
public class SerialSingleton implements Serializable {
public final static SerialSingleton INSTANCE = new SerialSingleton();
private SerialSingleton() {}
public static SerialSingleton getInstance() { return INSTANCE; }
private Object readResolve() { return INSTANCE; }
}
com.singleton.seriable.SerialSingleton@33909752
com.singleton.seriable.SerialSingleton@33909752
true
喜极而泣!!
冷静一下,emm为什么会这样呢??去看源码去看源码,看下ObjectInputStream的readObject()方法,因为是通过readObject方法拿到的s1呀 ~ ~
通过分析源码知道了在readObject方法中,会通过反射去找无参的readResolve() 方法,并调用。所以通过增加readResolve()方法返回实例可以解决单例模式被破坏的问题。