【发布时间】:2014-06-03 00:09:48
【问题描述】:
如果我使用序列化代理模式,我应该为包含类提供自定义的writeObject 方法,还是只提供代理?我什至应该为代理使用自定义表单吗?我已经阅读了 Effective Java 关于序列化的章节,但对自定义表单和代理模式并不清楚。
【问题讨论】:
标签: java file serialization file-io
如果我使用序列化代理模式,我应该为包含类提供自定义的writeObject 方法,还是只提供代理?我什至应该为代理使用自定义表单吗?我已经阅读了 Effective Java 关于序列化的章节,但对自定义表单和代理模式并不清楚。
【问题讨论】:
标签: java file serialization file-io
当您使用序列化代理模式时,原始类的实例永远不会使用“正常”序列化机制进行序列化。所以如果原始类有一个writeObject 实现,它永远不会被调用。
虽然您不需要writeObject 方法,但您可能应该在原始类中编写readObject 方法。如果在您引入代理之前对它们进行了序列化,那么您的类的较旧的序列化实例可能已经存在。或者,有人可能伪造了一个看起来像原始类的传统序列化形式的字节流。反序列化这将绕过代理并可能创建原始类的格式错误的实例。为了防止这种情况,请从原始类的readObject 方法中无条件地抛出异常,以防止任何反序列化绕过代理。 (这在 Effective Java 中有所提及,但重要的是我觉得我应该在这里重复一遍。)
至于串行代理的自定义形式,它不是绝对必要的。 Effective Java 建议串行代理类设计得简单明了,可以使用默认的序列化形式。如果这对您有用,很好,您可以使用默认表单。但是我开始看到的另一种模式是,一个序列化代理被用作几个不同的可序列化类的代理。在这种情况下,代理类不是嵌套类,而只是同一包中的包私有类。代理可能希望有一个自定义的序列化表单,以便它可以改变写入的序列化数据,具体取决于它是代理的哪个类。
JDK 中新的java.time 类的序列化实现了这一点,使用单个串行代理来处理多个数据类。请参阅Ser.java 文件以了解这是如何完成的。不过,这有点复杂,因为它使用Externalizable 接口而不是特殊的序列化方法,并且它委托给数据类来进行读取和写入。但是你可以看到这些原则在起作用。
【讨论】:
原始类应该有一个返回代理类实例的writeReplace()方法,代理类应该有一个返回原始类实例的readResolve()方法。
我应该为包含的类提供一个自定义的 writeObject 方法
没有。
还是只是代理?
没有。
我是否应该为代理使用自定义表单?
没有。使代理类尽可能简单,即 POJO。
【讨论】: