作者:万万558 | 来源:互联网 | 2024-12-27 15:06
在 Java 编程语言中,实现序列化的类需要实现 java.io.Serializable 接口。通过实现此接口,一个类可以将其状态保存到字节流中,并在稍后的时间点从该字节流恢复其状态。未实现 Serializable 接口的类将无法进行序列化或反序列化操作。所有可序列化类的子类也都是可序列化的。
Serializable 接口本身没有定义任何方法或字段,它仅用于标识某个类具有序列化语义。为了使非序列化类的子类能够被序列化,子类可以负责保存和恢复父类的公共、受保护以及(如果可访问)包级字段。但前提是父类必须有一个可访问的无参构造函数来初始化其状态。否则,在运行时会抛出异常。
在反序列化过程中,非序列化类的字段将使用公共或受保护的无参构造函数进行初始化。可序列化的子类字段则会从输入流中恢复。当遍历对象图时,如果遇到不支持 Serializable 接口的对象,则会抛出 NotSerializableException 异常并指明该不可序列化的类。
为了在序列化和反序列化期间处理特殊情况,类可以实现以下特殊方法:
- private void writeObject(java.io.ObjectOutputStream out) throws IOException;
- private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
- private void readObjectNoData() throws ObjectStreamException;
writeObject 方法负责将对象的状态写入输出流,以便 readObject 方法可以在反序列化时恢复这些状态。readObject 方法负责从输入流读取数据并恢复对象的字段。readObjectNoData 方法用于在反序列化流未列出给定类作为对象的超类时初始化对象状态。
此外,某些类可能需要指定替代对象用于序列化或反序列化。为此,它们可以分别实现 writeReplace 和 readResolve 方法:
- ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
- ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
每个可序列化的类都有一个版本号,称为 serialVersionUID,用于确保发送方和接收方加载的类是兼容的。建议显式声明 serialVersionUID 以避免不同编译器实现导致的不一致问题。数组类不能显式声明 serialVersionUID,因此总是使用默认计算值,但对于数组类来说,匹配 serialVersionUID 的要求被放宽。