上面一篇文章中提到了单例模式,那么当单例模式遇到了序列化,会怎样呢?
首先我们看一下,要生成一个新的对象有几种方式:
1. 通过new 创建实例
2. 调用clone()
3. 通过反射
4. 反序列化
下面再看一个静态内置类的单例模式:
public class Myobject{
private static class MyobjectHandler{
private static Myobject myobject = new Myobject();
}
private Myobject(){}
public static Myoject getInstance(){
return MyojectHandler.myoject;
}
}
私有化构造方法的原意就是为了避免通过new创建实例,但如果上面这个类实现了可序列化借口,他还是单例模式吗?答案是否定的。
再看下面的例子:
public class Myobject implements Serializable{
private static class MyobjectHandler{
private static Myobject myobject = new Myobject();
}
private Myobject(){}
public static Myoject getInstance(){
return MyojectHandler.myoject;
}
}
然后做一个测试:
public class SaveAndRead{
public static void main(String[] args){
try{
Myobject myobject = Myobject.getInstance();
FileOutputStream fosRef = new FileOutputStream(new File(“myobjectFile.txt”));
ObjectOutputStream oosRef = new FileOutputStream(fosRef);
oosRef.writeObject(myObject);
oosRef.close();
fosRef.close();
System.out.println(myObject.hashCode());
}catch(Exception e){
e.printStackTrace();
}
try{
FileInputStream fisRef = new FileInputStream(new File(“myobjectFile.txt”));
ObjectInputStream iosRef = new FileInputStream(fisRef);
MyObject myobject = (MyObject) iosRef.readobject();
iosRef.close();
fisRef.close();
System.out.println(myObject.hashCode());
}catch(Exception e){
e.printStackTrace();
}
}
}
运行结果为:
15218966
54112
由以上测试可知,序列化已经破坏了单例模式,那是否就无可挽回了呢,当然不是?
我们可以这样修改:
public class Myobject implements Serializable{
private static class MyobjectHandler{
private static Myobject myobject = new Myobject();
}
private Myobject(){}
public static Myoject getInstance(){
return MyojectHandler.myoject;
}
protected Object readResolve() throws ObjectStreamException{
System.out.println(“调用了readResolve”);
Return MyObjectHandler.myObject;
}}
在运行上面的测试,结果是:
33219526
调用了readResolve
33219526
问题解决,其实单例模式还有一个最大的天敌,那就是反射,因为反射的权限太高了,他甚至可以访问类的私有方法,所以单例碰到反射恐怕就回天无术了,所以,在单例模式中切忌使用反射!!!!!!