显式声明默认 Java class 序列化方法的原因是什么?
What is the reason to explicitly declare default Java class serialization methods?
我定期看到 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
。是否有任何理由仅使用默认实现来声明写/读方法?我厌倦了关于代码重复的分析器警告。
没有看到关于此主题的任何真正清晰的指南。一切都有些过时或相当主观。
自定义序列化时只需要实现writeObject
和readObject
即可。对于 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. 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. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. 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. 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.
http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html
ObjectInputStream#defaultReadObject 和 ObjectOutputStream#defaultWriteObject 方法是为以下情况提供的:您想要使用默认值写入字段以及您有其他信息要读取或写入,或者如果您想要修改读取或写入的内容。如果您不想添加或更改任何内容,那么与仅实现 Serializable 相比,添加显式调用没有任何优势。
Java Object Serialization Specification 似乎是一个很好的参考,第 1.7 节(访问 Class 的可序列化字段)说:
The default mechanism is used automatically when reading or writing objects that implement the Serializable interface and do no further customization. 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. 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.
我定期看到 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
。是否有任何理由仅使用默认实现来声明写/读方法?我厌倦了关于代码重复的分析器警告。
没有看到关于此主题的任何真正清晰的指南。一切都有些过时或相当主观。
自定义序列化时只需要实现writeObject
和readObject
即可。对于 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. 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. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. 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. 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.
http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html
ObjectInputStream#defaultReadObject 和 ObjectOutputStream#defaultWriteObject 方法是为以下情况提供的:您想要使用默认值写入字段以及您有其他信息要读取或写入,或者如果您想要修改读取或写入的内容。如果您不想添加或更改任何内容,那么与仅实现 Serializable 相比,添加显式调用没有任何优势。
Java Object Serialization Specification 似乎是一个很好的参考,第 1.7 节(访问 Class 的可序列化字段)说:
The default mechanism is used automatically when reading or writing objects that implement the Serializable interface and do no further customization. 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. 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.