为什么readObject方法必须调用defaultReadObject来保持向后和向前兼容性

时间:2015-10-27 09:05:23

标签: java serialization

我正在浏览 Effective Java,第75项:

  

如果所有实例字段都是瞬态的,则在技术上允许   不需要调用defaultWriteObject和defaultReadObject,但是   不推荐。即使所有实例字段都是瞬态的,   调用defaultWriteObject会影响序列化表单,从而导致   大大增强了灵活性生成的序列化表单使其成为现实   可以在以后的版本中添加非瞬态实例字段   保持向后和向前兼容性。如果是一个实例   在更高版本中序列化并在早期版本中反序列化,   添加的字段将被忽略。有早期版本的readObject   方法无法调用defaultReadObject,反序列化会   使用StreamCorruptedException失败

问题是为什么需要调用defaultReadObject / defaultWriteObject来保持向后和向前兼容性?

你能用一个例子解释一下吗?

为什么添加的字段会被忽略?

为什么会抛出StreamCorruptedException?

2 个答案:

答案 0 :(得分:0)

因为那是默认情况。如果你添加这些方法,你必须至少做一些如果它们不存在会发生的事情。否则,您将无法以兼容的方式读取/写入流。你不能完全取代原本写的内容而不会有兼容性。

除非你可以同时神奇地改变两端,否则任何地方都没有永久序列化的流,例如在文件或数据库中。

答案 1 :(得分:0)

你的问题的答案实际上在你刚才提供的摘录中(虽然它有点模糊,我承认)。关键部分是:

  

如果某个实例在更高版本中序列化并在其中反序列化   在早期版本中,添加的字段将被忽略。 早些时候   version的readObject方法无法调用defaultReadObject ,即   反序列化将失败[...]

想象一下以下示例: 你有一个只有瞬态字段的对象。您决定跳过defaultWriteObject/defaultReadObject次来电,因为您认为您不需要

然后向程序添加新功能,并为此对象添加一些非瞬态字段。这次你可以正确地调用defaultWriteObject,并且你希望旧版本的应用程序仍然可以运行(当然忽略新字段)。但它没有赢。您没有忽略刚添加的新字段,因为它在那里发现了意外数据。