模块  java.base
软件包  java.io

Interface Serializable

  • All Known Subinterfaces:
    AttributeAttributeAttributesCertPathValidatorException.ReasonConnector.ArgumentConnector.BooleanArgumentConnector.IntegerArgumentConnector.SelectedArgumentConnector.StringArgumentControlDescriptorDHPrivateKeyDHPublicKeyDocAttributeDSAPrivateKeyDSAPublicKeyECPrivateKeyECPublicKeyExtendedRequestExtendedResponseExternalizableKeyNameNotificationFilterPBEKeyPrintJobAttributePrintRequestAttributePrintServiceAttributePrivateKeyPublicKeyQueryExpRelationTypeRemoteRefRSAMultiPrimePrivateCrtKeyRSAPrivateCrtKeyRSAPrivateKeyRSAPublicKeySecretKeyServerRefSupportedValuesAttributeUnsolicitedNotificationValueExpXECPrivateKeyXECPublicKey

    public interface Serializable
    实现java.io.Serializable接口的类启用了类的可序列化。

    警告:不受信任数据的反序列化本质上是危险的,应该避免。 应根据Secure Coding Guidelines for Java SE的“序列化和反序列化”部分仔细验证不受信任的数据。 Serialization Filtering描述了防御性使用串行过滤器的最佳实践。

    未实现此接口的类将不会将其任何状态序列化或反序列化。 可序列化类的所有子类型本身都是可序列化的。 序列化接口没有方法或字段,仅用于标识可序列化的语义。

    为了允许序列化非可序列化类的子类型,子类型可以承担保存和恢复超类型的公共,受保护和(如果可访问)包字段的状态的责任。 只有当它扩展的类具有可访问的no-arg构造函数来初始化类的状态时,子类型才可以承担此责任。 如果不是这种情况,则声明类Serializable是错误的。 将在运行时检测到错误。

    在反序列化期间,将使用类的public或protected no-arg构造函数初始化非可序列化类的字段。 必须可以对可序列化的子类访问no-arg构造函数。 可序列化子类的字段将从流中恢复。

    遍历图形时,可能会遇到不支持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来调用保存Object字段的默认机制。 该方法不需要关注属于其超类或子类的状态。 通过使用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相同的调用规则和可访问性规则。

    序列化运行时将每个可序列化类与版本号相关联,称为serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已加载与该序列化兼容的该对象的类。 如果接收者已经为具有与相应发送者类别不同的serialVersionUID的对象加载了类,则反序列化将导致InvalidClassException 可序列化类可以通过声明名为"serialVersionUID"必须为static,final和long类型的字段来显式声明其自己的serialVersionUID:

      ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; 
    如果可序列化类未显式声明serialVersionUID,则序列化运行时将基于类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。 但是, 强烈建议所有可序列化类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节高度敏感,这些细节可能因编译器实现而异,因此在反序列化期间可能会导致意外的InvalidClassException 因此,为了保证跨不同java编译器实现的一致serialVersionUID值,可序列化类必须声明显式serialVersionUID值。 强烈建议显式serialVersionUID声明尽可能使用private修饰符,因为此类声明仅适用于立即声明的类 - serialVersionUID字段不适用于继承成员。 数组类不能声明显式的serialVersionUID,因此它们始终具有默认的计算值,但是对于数组类,不需要匹配serialVersionUID值。
    从以下版本开始:
    1.1
    另请参见:
    ObjectOutputStreamObjectInputStreamObjectOutputObjectInputExternalizable