声明Java类默认序列化方法的原因是什么?

4

我会定期看到具有以下结构的Java类:

class MyClass implements Serializable {

    private static final long serialVersionUID = 1L;

    // ...

    private void writeObject(final java.io.ObjectOutputStream s) throws IOException {
        s.defaultWriteObject();
    }

    private void readObject(final java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
        s.defaultReadObject();
    }

}

据我了解,对于默认序列化,您只需要声明实现serializable接口并定义serialVersionUID即可。是否有必要声明仅具有默认实现的写入/读取方法?我已经厌倦了关于代码重复的分析器警告。
我没有看到任何真正清晰的指南来介绍这个主题。所有内容要么过时了,要么非常主观。

1
通常是通过几次点击生成的代码。版本仍停留在1,没有进行自定义序列化也说明了这一点。serialVersionUID声称是不可更改的序列化。 - Joop Eggen
2个回答

4
ObjectInputStream#defaultReadObject和ObjectOutputStream#defaultWriteObject方法用于在您想要使用默认字段并且有其他信息需要读取或写入的情况下,或者如果您想修改读取或写入的内容时。如果您不想添加或更改任何内容,则添加显式调用与仅实现Serializable相比没有优势。 Java Object Serialization Specification似乎是一个很好的参考资料,其中第1.7节(访问类的可序列化字段)说明:
默认机制在读取或写入实现Serializable接口且未进行进一步定制的对象时自动使用。可序列化字段映射到类的相应字段,并从这些字段将值写入流中,或者分别读入并分配值。如果类提供了writeObject和readObject方法,则可以通过调用defaultWriteObject和defaultReadObject来调用默认机制。当实现writeObject和readObject方法时,类有机会在写入或读取可序列化字段值之前或之后修改它们。

1
当您进行自定义序列化时,只需实现writeObjectreadObject。关于serialVersionUID,请阅读以下内容:
如果一个可序列化类没有明确声明serialVersionUID,则序列化运行时将根据类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范所述。然而,强烈建议所有可序列化类都明确声明serialVersionUID值,因为默认的serialVersionUID计算对编译器实现的类细节非常敏感,因此可能导致不期望的InvalidClassExceptions在反序列化期间发生。因此,为了保证在不同的Java编译器实现中具有一致的serialVersionUID值,可序列化类必须声明一个明确的serialVersionUID值。还强烈建议使用private修饰符来声明显式的serialVersionUID声明,因为这种声明仅适用于立即声明的类--serialVersionUID字段作为继承成员是无用的。数组类不能声明明确的serialVersionUID,因此它们始终具有默认计算值,但对于数组类,匹配serialVersionUID值的要求被豁免。

http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接