【问题标题】:Why does the defaultWriteObject function have to be called first when writing into an ObjectOutputStream?为什么写入 ObjectOutputStream 时必须先调用 defaultWriteObject 函数?
【发布时间】:2013-04-26 14:45:21
【问题描述】:

当我阅读Thinking in java中关于Serializable接口的时候,有一句话说:

如果使用默认机制写入对象的非瞬态部分,则必须调用 defaultWriteObject( ) 作为 writeObject( ) 中的第一个操作,并将 defaultReadObject( ) 作为 readObject( ) 中的第一个操作。

在docs.oracle.com 5.6.2:

添加 writeObject/readObject 方法 - 如果读取流的版本具有这些方法,那么 readObject 应该像往常一样读取通过默认序列化写入流的所需数据。在读取任何可选数据之前,它应该首先调用 defaultReadObject。 writeObject 方法应该像往常一样调用 defaultWriteObject 来写入所需的数据,然后可以写入可选的数据。

所以如果我不先打电话给defaultWriteObject,如果我在打电话之前写了别的东西,会有什么问题吗?我已经尝试过了,但它似乎在我的示例中仍然有效。那么如果有任何问题,在什么情况下会发生呢?

【问题讨论】:

  • 之所以如此,是因为如此。除非您在这里找到一位原始设计师,这是不太可能的,否则您在这里获得的任何东西或多或少都是无知的猜测。没有建设性。

标签: java serialization


【解决方案1】:

Java 对象序列化规范 在这个主题上含糊不清:

ObjectOutputStream 的defaultWriteObject 或writeFields 方法必须调用一次(并且仅调用一次),然后才能写入相应的readObject 方法恢复对象状态所需的任何可选数据;即使没有写入可选数据,defaultWriteObject 或 writeFields 仍必须调用一次。如果在写入可选数据(如果有)之前没有调用一次defaultWriteObject 或writeFields,那么在ObjectInputStream 无法解析类的情况下,实例反序列化的行为是undefined它定义了有问题的writeObject 方法。

这是一个old thread,它给出了可能出现问题的示例。

这里有一个 JBoss AS Jira ticket 和另一个例子。

【讨论】:

  • 我最近遇到了这个问题,它在接收器中导致了难以调试的 StreamCorruptedException,因此我强烈建议始终调用 defaultRead/WriteObject,即使您的类的所有成员都是瞬态的。
  • 这是否意味着它更多的是调用构造函数来构建对象?在序列化和反序列化之前?
【解决方案2】:

在 Effective Java 中有描述:

如果所有实例字段都是瞬态的,从技术上讲可以省略调用 defaultWriteObject 和 defaultReadObject ,但不建议这样做。即使所有实例字段都是瞬态的,调用 defaultWriteObject 也会影响序列化的表单,从而大大增强了灵活性。生成的序列化形式可以在以后的版本中添加非瞬态实例字段,同时保持向后和向前兼容性。如果实例在更高版本中被序列化并在更早版本中被反序列化,则添加的字段将被忽略。如果早期版本的 readObject 方法未能调用 defaultReadObject ,反序列化将失败并出现 StreamCorruptedException 。

【讨论】:

    【解决方案3】:

    我认为文档中的关键词是“应该”,这意味着您不必这样做。

    我认为这更像是一种最佳实践。如果我第一次阅读您的代码并看到您在第一行默认了读/写,我可以对自己说“好的,完成了 90% 的课程”,然后专注于您的自定义代码所有非瞬态、非静态的实例变量..

    最重要的是读/写顺序一致。除此之外,您可以随心所欲。

    【讨论】:

      【解决方案4】:

      我认为那是因为你知道你在双方都做了什么,并且在相反的情况下做“相同”或更好......

      但是:如果其他程序员在不知道您不使用默认值的情况下针对您的序列化编写反序列化,他可能将使用推荐的 defaultReadObject,然后遇到奇怪的异常。

      【讨论】:

        猜你喜欢
        • 2011-06-18
        • 1970-01-01
        • 2017-01-21
        • 2010-10-28
        • 2022-01-17
        • 1970-01-01
        • 1970-01-01
        • 2016-06-09
        • 1970-01-01
        相关资源
        最近更新 更多