java單例模式之readResolve()
阿新 • • 發佈:2019-02-11
不考慮反射這種極端情況,還有一種情況會破壞單例模式。
序列化,反序列化!
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;
}
}