- 所有已知的子接口:
Attribute
,Attribute
,Attributes
,CertPathValidatorException.Reason
,Connector.Argument
,Connector.BooleanArgument
,Connector.IntegerArgument
,Connector.SelectedArgument
,Connector.StringArgument
,Control
,Descriptor
,DHPrivateKey
,DHPublicKey
,DocAttribute
,DSAPrivateKey
,DSAPublicKey
,ECPrivateKey
,ECPublicKey
,EdECPrivateKey
,EdECPublicKey
,ExtendedRequest
,ExtendedResponse
,Externalizable
,Key
,Name
,NotificationFilter
,PBEKey
,PrintJobAttribute
,PrintRequestAttribute
,PrintServiceAttribute
,PrivateKey
,PublicKey
,QueryExp
,RelationType
,RemoteRef
,RSAMultiPrimePrivateCrtKey
,RSAPrivateCrtKey
,RSAPrivateKey
,RSAPublicKey
,SecretKey
,ServerRef
,SupportedValuesAttribute
,UnsolicitedNotification
,ValueExp
,XECPrivateKey
,XECPublicKey
Warning: Deserialization of untrusted data is inherently dangerous and should be avoided. Untrusted data should be carefully validated according to the "Serialization and Deserialization" section of the Secure Coding Guidelines for Java SE. Serialization Filtering describes best practices for defensive use of serial filters.
不实现此接口的类将不会对其任何状态进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。不可序列化类的子类型可以被序列化和反序列化。在序列化期间,不会为不可序列化超类的字段写入任何数据。在反序列化期间,不可序列化超类的字段将使用第一个(最底层)不可序列化超类的无参数构造函数进行初始化。正在反序列化的子类必须可以访问此构造函数。如果不是这种情况,则声明类 Serializable 是错误的;该错误将在运行时检测到。可序列化子类型可能承担保存和恢复不可序列化超类型的公共、受保护和(如果可访问)包访问字段的状态的责任。有关反序列化过程的详细规范,包括可序列化和不可序列化类的处理,请参阅 Java 对象序列化规范, 第 3.1 节。
遍历图时,可能会遇到不支持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 方法可以恢复它。可以通过调用 out.defaultWriteObject 来调用保存对象字段的默认机制。该方法不需要关心属于其超类或子类的状态。通过使用 writeObject 方法或使用 DataOutput 支持的基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存状态。
readObject 方法负责从流中读取并恢复类字段。它可以调用 in.defaultReadObject 来调用默认机制来恢复对象的非静态和非瞬态字段。 defaultReadObject 方法使用流中的信息将保存在流中的对象的字段分配给当前对象中相应命名的字段。这处理了类已经演变为添加新字段的情况。该方法不需要关心属于其超类或子类的状态。通过从 ObjectInputStream 读取各个字段的数据并对对象的适当字段进行分配来恢复状态。 DataInput 支持读取原始数据类型。
如果序列化流未将给定类列为反序列化对象的超类,则 readObjectNoData 方法负责为其特定类初始化对象的状态。如果接收方使用与发送方不同版本的反序列化实例类,并且接收方版本扩展了发送方版本未扩展的类,则可能会发生这种情况。如果序列化流被篡改,也可能发生这种情况;因此,尽管存在“敌对”或不完整的源流,readObjectNoData 可用于正确初始化反序列化对象。
在将对象写入流时需要指定要使用的替代对象的可序列化类应使用确切的签名实现此特殊方法:
ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
如果此 writeReplace 方法存在并且可以从被序列化对象的类中定义的方法访问,则序列化会调用此方法。因此,该方法可以具有私有的、受保护的和包私有的访问权限。对此方法的子类访问遵循 java 可访问性规则。
当从流中读取实例时需要指定替换的类应使用确切的签名实现此特殊方法。
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
此 readResolve 方法遵循与 writeReplace 相同的调用规则和可访问性规则。
枚举类型都是可序列化的,并在序列化和反序列化期间接受由 Java 对象序列化规范 定义的处理。对于枚举类型,忽略上面讨论的特殊处理方法的任何声明。
记录类可以实现 Serializable
并接受 Java 对象序列化规范, Section 1.13, "Serialization of Records" 定义的处理。对于记录类型,忽略上面讨论的特殊处理方法的任何声明。
序列化运行时与每个可序列化类关联一个版本号,称为 serialVersionUID,在反序列化期间使用它来验证序列化对象的发送方和接收方是否已为该对象加载与序列化兼容的类。如果接收方为对象加载了一个类,该类的 serialVersionUID 与相应发送方类的类不同,则反序列化将导致 InvalidClassException
。可序列化类可以通过声明一个名为 "serialVersionUID"
的字段来显式声明自己的 serialVersionUID,该字段必须是静态的、最终的且类型为 long
:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;如果可序列化类没有显式声明 serialVersionUID,那么序列化运行时将根据该类的各个方面计算该类的默认 serialVersionUID 值,如 Java 对象序列化规范。 本规范中所述,该规范将枚举类型的 serialVersionUID 定义为 0L .但是,strongly recommended 除了枚举类型之外的所有可序列化类都显式声明 serialVersionUID 值,因为默认的 serialVersionUID 计算对类细节高度敏感,这些细节可能因编译器实现而异,因此可能在反序列化期间导致意外的
InvalidClassException
s。因此,为了保证在不同的 java 编译器实现中具有一致的 serialVersionUID 值,可序列化类必须声明一个显式的 serialVersionUID 值。还强烈建议显式 serialVersionUID 声明尽可能使用 private
修饰符,因为此类声明仅适用于立即声明的类——serialVersionUID 字段作为继承成员没有用处。数组类无法声明显式的 serialVersionUID,因此它们始终具有默认的计算值,但数组类放弃了匹配 serialVersionUID 值的要求。
- 自从:
- 1.1
- 参见: