用于序列化单例的瞬态

有效的Java – 为了保持单例保证,您必须将所有实例字段声明为瞬态并提供“readResolve”方法。 我们通过在这里声明瞬态场来实现什么目标? 这是一个示例:

.... .... public final class MySingleton implements Serializable{ private int state; private MySingleton() { state =15; } private static final MySingleton INSTANCE = new MySingleton(); public static MySingleton getInstance() { return INSTANCE; } public int getState(){return state;} public void setState(int val){state=val;} private Object readResolve() throws ObjectStreamException { return INSTANCE; } public static void main(String[] args) { MySingleton c = null; try { c=MySingleton.getInstance(); c.setState(25); FileOutputStream fs = new FileOutputStream("testSer.ser"); ObjectOutputStream os = new ObjectOutputStream(fs); os.writeObject(c); os.close(); } catch (Exception e) { e.printStackTrace(); } try { FileInputStream fis = new FileInputStream("testSer.ser"); ObjectInputStream ois = new ObjectInputStream(fis); c = (MySingleton) ois.readObject(); ois.close(); System.out.println("after deser: contained data is " + c.getState()); } catch (Exception e) { e.printStackTrace(); } } } 

无论我是否将’state’变量声明为瞬态变量,我都将c.getState()gettign打印为25.我在这里遗漏了什么?

通过使属性瞬态获得的是您不会序列化状态。 序列化它是不必要的,因为它无论如何都被readResolve()方法丢弃了。

如果状态包含int,则无关紧要。 但如果状态是对象的复杂图形,则会产生显着的性能差异。 当然,如果状态不可序列化,则您没有任何其他选择。

也就是说,序列化单例是值得怀疑的。

无论我是否将’state’变量声明为瞬态变量,我都将c.getState()gettign打印为25.我在这里遗漏了什么?

您替换反序列化对象,因为readResolve()返回MySingleton的私有静态实例,从而覆盖反序列化返回的实例。

 try { c=MySingleton.getInstance(); c.setState(25); FileOutputStream fs = new FileOutputStream("testSer.ser"); ObjectOutputStream os = new ObjectOutputStream(fs); os.writeObject(c); os.close(); } 

您将获得25,因为您在对象中设置了该值。 参考上面的代码。 我想你期待答案是15?