單例模式的序列化與反序列化實現需要實現readResolve()方法
阿新 • • 發佈:2018-11-19
package com.linruby.singleton; import java.io.Serializable; public class SingletonObject implements Serializable { private static final SingletonObject instance = new SingletonObject(); private String name = "linruby12"; private int age = 37; private SingletonObject() { } public static SingletonObject getInstance() { return instance; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } private Object readResolve() { return SingletonObject.getInstance(); } }
package com.linruby.singleton; import java.io.*; import static java.lang.System.out; import static java.lang.System.setOut; public class ClinetMain { public static void main(String[] args) { SingletonObject instance = SingletonObject.getInstance(); FileOutputStream fout = null; ObjectOutputStream outObj = null; FileInputStream fin=null; ObjectInputStream inObj = null; try { fout = new FileOutputStream("d:/linruby12.obj"); outObj = new ObjectOutputStream(fout); outObj.writeObject(instance); outObj.flush(); fin = new FileInputStream("d:/linruby12.obj"); inObj = new ObjectInputStream(fin); SingletonObject instance2 = (SingletonObject)inObj.readObject(); System.out.println(instance); System.out.println(instance2); System.out.println(instance2.getName()); System.out.println(instance2.getAge()); } catch (Exception e) { e.printStackTrace(); } finally { if (fout != null) { try { fout.close(); } catch (IOException e) { e.printStackTrace(); } } if (outObj != null) { try { outObj.close(); } catch (IOException e) { e.printStackTrace(); } } ..... } } }
結果:
[email protected]
[email protected]
linruby12
37
那麼這個readResolve()方法是從哪來的,為什麼加上之後就能返回同一例項了呢?
找到ObjectInputStream類的
/** * Reads and returns "ordinary" (i.e., not a String, Class, * ObjectStreamClass, array, or enum constant) object, or null if object's * class is unresolvable (in which case a ClassNotFoundException will be * associated with object's handle). Sets passHandle to object's assigned * handle. */ private Object readOrdinaryObject(boolean unshared) throws IOException { if (bin.readByte() != TC_OBJECT) { throw new InternalError(); } ObjectStreamClass desc = readClassDesc(false); desc.checkDeserialize(); Class<?> cl = desc.forClass(); if (cl == String.class || cl == Class.class || cl == ObjectStreamClass.class) { throw new InvalidClassException("invalid class descriptor"); } Object obj; try { obj = desc.isInstantiable() ? desc.newInstance() : null; } catch (Exception ex) { throw (IOException) new InvalidClassException( desc.forClass().getName(), "unable to create instance").initCause(ex); } passHandle = handles.assign(unshared ? unsharedMarker : obj); ClassNotFoundException resolveEx = desc.getResolveException(); if (resolveEx != null) { handles.markException(passHandle, resolveEx); } if (desc.isExternalizable()) { readExternalData((Externalizable) obj, desc); } else { readSerialData(obj, desc); } handles.finish(passHandle); // 這個位置呼叫readResolve方法 if (obj != null && handles.lookupException(passHandle) == null && desc.hasReadResolveMethod()) { Object rep = desc.invokeReadResolve(obj); if (unshared && rep.getClass().isArray()) { rep = cloneArray(rep); } if (rep != obj) { handles.setObject(passHandle, obj = rep); } } return obj; }