简体   繁体   English

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

[英]What is the reason to explicitly declare default Java class serialization methods?

I periodically see Java classes with the following structure: 我定期看到具有以下结构的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();
    }

}

As I understand for default serialization you only need to declare implementation of serializable interface and define serialVersionUID . 据我所知,对于默认序列化,您只需要声明可serializable接口的实现并定义serialVersionUID Is there any reason to declare write / read methods with just default implementation? 是否有任何理由使用默认实现声明写/读方法? I am tired from analyzer warnings about code duplication. 我厌倦了关于代码重复的分析器警告。

Don't see any really clear guide for this topic. 没有看到任何关于这个主题的非常明确的指南。 Everything either is somewhat outdated or pretty subjective. 一切都有点过时或非常主观。

The ObjectInputStream#defaultReadObject and ObjectOutputStream#defaultWriteObject methods are provided for cases where you want to write the fields using the defaults plus you have other information to read or write, or if you want to modify what gets read or written. ObjectInputStream#defaultReadObject和ObjectOutputStream#defaultWriteObject方法适用于您希望使用默认值编写字段以及您有其他读取或写入信息,或者您想要修改读取或写入内容的情况。 If you don't want to add or change anything, there's no advantage to adding explicit calls over just implementing Serializable. 如果您不想添加或更改任何内容,则仅在实现Serializable时添加显式调用没有任何优势。

The Java Object Serialization Specification seems like a good reference for this, section 1.7 (Accessing Serializable Fields of a Class) says: Java对象序列化规范似乎是一个很好的参考,第1.7节(访问类的可序列化字段)说:

The default mechanism is used automatically when reading or writing objects that implement the Serializable interface and do no further customization. 在读取或编写实现Serializable接口的对象时不会自动使用默认机制,并且不进行进一步的自定义。 The serializable fields are mapped to the corresponding fields of the class and values are either written to the stream from those fields or are read in and assigned respectively. 可序列化字段映射到类的相应字段,值可以从这些字段写入流,也可以分别读入和分配。 If the class provides writeObject and readObject methods, the default mechanism can be invoked by calling defaultWriteObject and defaultReadObject. 如果类提供writeObject和readObject方法,则可以通过调用defaultWriteObject和defaultReadObject来调用默认机制。 When the writeObject and readObject methods are implemented, the class has an opportunity to modify the serializable field values before they are written or after they are read. 实现writeObject和readObject方法时,类有机会在写入或读取之后修改可序列化字段值。

You only need to implement writeObject and readObject when you do custom serialization. 您只需要在执行自定义序列化时实现writeObjectreadObject For serialVersionUID please read the following: 对于serialVersionUID,请阅读以下内容:

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. 如果可序列化类未显式声明serialVersionUID,则序列化运行时将基于类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。 However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. 但是,强烈建议所有可序列化类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节高度敏感,这些细节可能因编译器实现而异,因此在反序列化期间可能导致意外的InvalidClassExceptions。 Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. 因此,为了保证跨不同java编译器实现的一致的serialVersionUID值,可序列化类必须声明显式的serialVersionUID值。 It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. 强烈建议显式serialVersionUID声明尽可能使用private修饰符,因为此类声明仅适用于立即声明的类 - serialVersionUID字段作为继承成员无用。 Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes. 数组类不能声明显式的serialVersionUID,因此它们始终具有默认的计算值,但是对于数组类,不需要匹配serialVersionUID值。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM