标签:技术分享 creates fail 接受 UI adr turn 防止 不能
思想:
如果一个单例类,无论是用什么样的方式设计,一旦被间接或者直接实现 Serializable 接口之后,就要多增加一点考虑,就是在类被反序列化之后,也要保证单例。
1 public class SerializableSingletonFail implements Serializable { 2 3 private static final long serialVersionUID = 3355486892283807446L; 4 5 private static final SerializableSingletonFail instance = new SerializableSingletonFail(); 6 7 private SerializableSingletonFail() { 8 if (instance != null) { 9 throw new IllegalStateException(); 10 } 11 } 12 13 public static final SerializableSingletonFail getInstance() { 14 return instance; 15 } 16 17 }
以上的类,是一个单例的简单饿汉模式实现,只是实现了 Serializable 接口。从类名上看就知道,这样做不能保证单例。
每一个类中,有两个很特殊的方法,分别是 writeReplace() 和 readResolve() 。
前者保证,无论从什么对象序列化,只要是序列化这个类,都会把 writeReplace() 的返回对象序列化进文件;而后者保证,无论从什么文件反序列化,都会反序列化成 readResolve() 的返回对象。
这两个方法,对于方法签名有着严格的限定,包括入参(没有入参)和返回类型(Object),但是可以接受抛出不同的异常。
一旦满足以上这点,即是将方法设为 private,而且没有任何调用,编译器也不会提示警告。而且建议讲方法设为 private,防止误操作。
1 public class SerializableSingleton implements Serializable { 2 3 private static final long serialVersionUID = -6451544700567522443L; 4 5 private static final SerializableSingleton instance = new SerializableSingleton(); 6 7 private SerializableSingleton() { 8 if (instance != null) { 9 throw new IllegalStateException(); 10 } 11 } 12 13 public static final SerializableSingleton getInstance() { 14 return instance; 15 } 16 17 private Object readResolve() { 18 return instance; 19 } 20 21 }
1 public class SerializableSingletonTest { 2 3 private final String uri1 = "./src/test/resources/serialable1.txt"; 4 private final String uri2 = "./src/test/resources/serialable2.txt"; 5 6 public void createSerialFile() { 7 SerializableSingletonFail singleton1 = SerializableSingletonFail.getInstance(); 8 SerializableSingleton singleton2 = SerializableSingleton.getInstance(); 9 try (FileOutputStream fos1 = new FileOutputStream(uri1); ObjectOutputStream oos1 = new ObjectOutputStream(fos1); 10 FileOutputStream fos2 = new FileOutputStream(uri2); ObjectOutputStream oos2 = new ObjectOutputStream(fos2);) { 11 oos1.writeObject(singleton1); 12 oos2.writeObject(singleton2); 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } 16 } 17 18 @Test 19 public void testFailure() { 20 SerializableSingletonFail singleton1 = SerializableSingletonFail.getInstance(); 21 SerializableSingletonFail singleton2 = null; 22 // 反序列化 23 try (FileInputStream fio = new FileInputStream(uri1); ObjectInputStream ois = new ObjectInputStream(fio);) { 24 singleton2 = (SerializableSingletonFail) ois.readObject(); 25 } catch (Exception e) { 26 e.printStackTrace(); 27 } 28 Assert.assertNotSame(singleton1, singleton2); 29 } 30 31 @Test 32 public void testSuccess() { 33 SerializableSingleton singleton1 = SerializableSingleton.getInstance(); 34 SerializableSingleton singleton2 = null; 35 // 反序列化 36 try (FileInputStream fio = new FileInputStream(uri2); ObjectInputStream ois = new ObjectInputStream(fio);) { 37 singleton2 = (SerializableSingleton) ois.readObject(); 38 } catch (Exception e) { 39 e.printStackTrace(); 40 } 41 Assert.assertSame(singleton1, singleton2); 42 } 43 44 }
设计模式(一)单例模式:实现 Serializable 接口之后的额外操作
标签:技术分享 creates fail 接受 UI adr turn 防止 不能
原文地址:http://www.cnblogs.com/jing-an-feng-shao/p/7501812.html