Java序列化:readObject()与readResolve()
有效的Java和其他资源提供了一个相当不错的解释,说明在使用可序列化的Java类时如何以及何时使用readObject()方法。 另一方面,readResolve()方法仍然有点神秘。 基本上我find的所有文件都只提到了其中的一个,或者只提到了两个。
尚未回答的问题是:
- 这两种方法有什么区别?
- 什么时候应该采用哪种方法?
- readResolve()应该如何使用,特别是在返回什么?
我希望你能对这个问题有所了解。
readResolve
用于replace从stream中读取的对象。 我见过的唯一用途是强制单身人士; 读取对象时,将其replace为单例实例。 这确保没有人可以通过序列化和反序列化单例创build另一个实例。
在readObject
返回之后调用readResolve
(相反, writeReplace
在writeObject
之前调用,可能在不同的对象上)。 该方法返回的对象this
对象replace为返回给ObjectInputStream.readObject
的用户以及对该stream中的对象的任何更后面的引用。 它主要用于串行代理(参见Effective Java,2nd Ed,IIRC)。
当ObjectInputStream
从stream中读取一个对象并准备将其返回给调用者时,将调用readResolve
方法。 ObjectInputStream
检查对象的类是否定义了readResolve
方法。 如果方法已定义,则调用readResolve
方法以允许stream中的对象指定要返回的对象。 返回的对象应该是与所有用途兼容的types。 如果不兼容,则发现types不匹配时将抛出ClassCastException
。
readResolve可以用来改变通过readObject方法序列化的数据。 例如,xstream API使用此function来初始化一些不在XML中的属性,以反序列化。
readResolve适用于您可能需要返回现有对象的情况,例如因为您正在检查应该合并的重复input,或者(例如,在最终一致的分布式系统中),因为这是在您意识到之前可能到达的更新任何旧版本。
readResolve()将确保序列化时的单例合同。
请参阅
readResolve方法
对于Serializable和Externalizable类,readResolve方法允许一个类在返回给调用者之前replace/parsing从stream中读取的对象。 通过实现readResolve方法,一个类可以直接控制自己被反序列化的实例的types和实例。 该方法定义如下:
ANY-ACCESS-MODIFIER对象readResolve()抛出ObjectStreamException;
当ObjectInputStream从stream中读取一个对象并准备将其返回给调用者时,将调用readResolve方法。 ObjectInputStream检查对象的类是否定义了readResolve方法。 如果方法已定义,则调用readResolve方法以允许stream中的对象指定要返回的对象。 返回的对象应该是与所有用途兼容的types。 如果不兼容,则发现types不匹配时将抛出ClassCastException 。
例如,可以创build一个Symbol类,其中每个符号绑定的单个实例只存在于虚拟机中。 将执行readResolve方法来确定该符号是否已被定义,并replace先前存在的等效Symbol对象以维护身份约束。 通过这种方式,Symbol对象的唯一性可以在序列化中保持不变。
当序列化被用来转换一个对象,以便它可以保存在文件中,我们可以触发一个方法,readResolve()。 该方法是私有的,并保存在同一个类中,在反序列化的同时对象正在被检索。 它确保了在反序列化之后,返回的对象与序列化的一样。 即, instanceSer.hashCode() == instanceDeSer.hashCode()
readResolve()方法不是一个静态方法。 在反序列化的时候调用in.readObject()
之后,它只是确保返回的对象与下面序列化的那个一样out.writeObject(instanceSer)
.. ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file1.ser")); out.writeObject(instanceSer); out.close();
这样,它也有助于单例devise模式的实现,因为每次都返回相同的实例。
public static ABCSingleton getInstance(){ return ABCSingleton.instance; //instance is static }
readObject()是ObjectInputStream类中的一个已有方法。在反序列化时读取对象readObject方法在内部检查被反序列化的类对象是否具有readResolve方法,如果readResolve方法存在,那么它将调用readResolve方法并返回相同实例。
所以写readResolve方法的强度是一个很好的实践,实现纯粹的单例devise模式,没有人可以通过序列化/反序列化来获得另一个实例。