模块  java.base
软件包  java.io

Class ObjectOutputStream

  • 实现的所有接口
    CloseableDataOutputFlushableObjectOutputObjectStreamConstantsAutoCloseable

    public class ObjectOutputStream
    extends OutputStream
    implements ObjectOutput, ObjectStreamConstants
    ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来完成对象的持久存储。 如果流是网络套接字流,则可以在另一个主机或另一个进程中重新构建对象。

    只有支持java.io.Serializable接口的对象才能写入流。 每个可序列化对象的类都被编码,包括类的类名和签名,对象的字段和数组的值,以及从初始对象引用的任何其他对象的闭包。

    writeObject方法用于将对象写入流。 任何对象,包括字符串和数组,都是用writeObject编写的。 可以将多个对象或基元写入流中。 必须从相应的ObjectInputstream中读取对象,这些对象具有与写入时相同的类型和顺序。

    也可以使用DataOutput中的适当方法将原始数据类型写入流中。 也可以使用writeUTF方法编写字符串。

    对象的默认序列化机制会写入对象的类,类签名以及所有非瞬态和非静态字段的值。 对其他对象的引用(瞬态或静态字段除外)也会导致这些对象被写入。 使用引用共享机制对对单个对象的多个引用进行编码,以便可以将对象的图形恢复为与写入原始图像时相同的形状。

    例如,编写一个可以由ObjectInputStream中的示例读取的对象:

      FileOutputStream fos = new FileOutputStream("t.tmp");
          ObjectOutputStream oos = new ObjectOutputStream(fos);
    
          oos.writeInt(12345);
          oos.writeObject("Today");
          oos.writeObject(new Date());
    
          oos.close(); 

    在序列化和反序列化过程中需要特殊处理的类必须使用这些精确签名实现特殊方法:

      private void readObject(java.io.ObjectInputStream stream)
         throws IOException, ClassNotFoundException;
     private void writeObject(java.io.ObjectOutputStream stream)
         throws IOException
     private void readObjectNoData()
         throws ObjectStreamException; 

    writeObject方法负责为其特定类编写对象的状态,以便相应的readObject方法可以恢复它。 该方法不需要关注属于对象的超类或子类的状态。 通过使用writeObject方法或使用DataOutput支持的原始数据类型的方法将各个字段写入ObjectOutputStream来保存状态。

    序列化不会写出任何未实现java.io.Serializable接口的对象的字段。 不可序列化的对象的子类可以是可序列化的。 在这种情况下,非可序列化类必须具有no-arg构造函数以允许其字段被初始化。 在这种情况下,子类负责保存和恢复非可序列化类的状态。 通常情况下,该类的字段可以访问(公共,包或受保护),或者有get和set方法可用于恢复状态。

    通过实现抛出NotSerializableException的writeObject和readObject方法,可以防止对象的序列化。 异常将被ObjectOutputStream捕获并中止序列化过程。

    实现Externalizable接口允许对象完全控制对象的序列化表单的内容和格式。 调用Externalizable接口的方法writeExternal和readExternal来保存和恢复对象状态。 当由类实现时,他们可以使用ObjectOutput和ObjectInput的所有方法编写和读取自己的状态。 对象负责处理发生的任何版本控制。

    枚举常量的序列化与普通的可序列化或可外部化的对象不同。 枚举常量的序列化形式仅由其名称组成; 不传输常量的字段值。 要序列化枚举常量,ObjectOutputStream会写入常量名称方法返回的字符串。 与其他可序列化或可外部化的对象一样,枚举常量可以作为随后出现在序列化流中的反向引用的目标。 枚举常量序列化的过程无法自定义; 在序列化期间,将忽略由枚举类型定义的任何特定于类的writeObject和writeReplace方法。 同样,任何serialPersistentFields或serialVersionUID字段声明也会被忽略 - 所有枚举类型都有一个固定的serialVersionUID为0L。

    原始数据(不包括可序列化字段和可外部化数据)将写入块数据记录中的ObjectOutputStream。 块数据记录由标题和数据组成。 块数据头由标记和标头后面的字节数组成。 连续的原始数据写入被合并到一个块数据记录中。 用于块数据记录的阻塞因子将是1024字节。 每个块数据记录将填充最多1024个字节,或者在块数据模式终止时写入。 调用ObjectOutputStream方法writeObject,defaultWriteObject和writeFields最初会终止任何现有的块数据记录。

    从以下版本开始:
    1.1
    另请参见:
    DataOutputObjectInputStreamSerializableExternalizableObject Serialization Specification, Section 2, Object Output Classes
    • 构造方法详细信息

      • ObjectOutputStream

        public ObjectOutputStream​(OutputStream out)
                           throws IOException
        创建一个写入指定OutputStream的ObjectOutputStream。 此构造函数将序列化流标头写入基础流; 调用者可能希望立即刷新流以确保接收ObjectInputStreams的构造函数在读取头时不会阻塞。

        如果安装了安全管理器,则此构造函数将在子类的构造函数直接或间接调用时检查“enableSubclassImplementation”SerializablePermission,该构造函数将覆盖ObjectOutputStream.putFields或ObjectOutputStream.writeUnshared方法。

        参数
        out - 要写入的输出流
        异常
        IOException - 如果在写入流标题时发生I / O错误
        SecurityException - 如果不受信任的子类非法覆盖安全敏感方法
        NullPointerException - 如果 outnull
        从以下版本开始:
        1.4
        另请参见:
        ObjectOutputStream()putFields()ObjectInputStream(InputStream)
      • ObjectOutputStream

        protected ObjectOutputStream()
                              throws IOException,
                                     SecurityException
        为完全重新实现ObjectOutputStream的子类提供一种方法,以便不必分配ObjectOutputStream的此实现刚刚使用的私有数据。

        如果安装了安全管理器,则此方法首先使用SerializablePermission("enableSubclassImplementation")权限调用安全管理器的checkPermission方法,以确保可以启用子类化。

        异常
        SecurityException - 如果存在安全管理器且其 checkPermission方法拒绝启用子类化。
        IOException - 如果在创建此流时发生I / O错误
        另请参见:
        SecurityManager.checkPermission(java.security.Permission)SerializablePermission
    • 方法详细信息

      • useProtocolVersion

        public void useProtocolVersion​(int version)
                                throws IOException
        指定写入流时要使用的流协议版本。

        此例程提供了一个钩子,以使当前版本的Serialization能够以向后兼容以前版本的流格式的格式进行写入。

        我们将尽一切努力避免引入额外的向后兼容性; 然而,有时没有其他选择。

        参数
        version - 使用java.io.ObjectStreamConstants中的ProtocolVersion。
        异常
        IllegalStateException - 如果在序列化任何对象后调用。
        IllegalArgumentException - 如果传入的版本无效。
        IOException - 如果发生I / O错误
        从以下版本开始:
        1.2
        另请参见:
        ObjectStreamConstants.PROTOCOL_VERSION_1ObjectStreamConstants.PROTOCOL_VERSION_2
      • writeObject

        public final void writeObject​(Object obj)
                               throws IOException
        将指定的对象写入ObjectOutputStream。 写入对象的类,类的签名,以及类的非瞬态和非静态字段及其所有超类型的值。 可以使用writeObject和readObject方法覆盖类的默认序列化。 该对象引用的对象是可传递的,因此可以通过ObjectInputStream重建完整的对象等效图。

        对于OutputStream和不应序列化的类的问题,会抛出异常。 所有异常对OutputStream都是致命的,而OutputStream处于不确定状态,并且调用者可以忽略或恢复流状态。

        Specified by:
        writeObject in interface ObjectOutput
        参数
        obj - 要写入的对象
        异常
        InvalidClassException - 序列化使用的类有问题。
        NotSerializableException - 某些要序列化的对象未实现java.io.Serializable接口。
        IOException - 底层OutputStream抛出的任何异常。
      • writeObjectOverride

        protected void writeObjectOverride​(Object obj)
                                    throws IOException
        子类用于覆盖默认writeObject方法的方法。 ObjectInputStream的可信子类调用此方法,该子类使用受保护的无参数构造函数构造ObjectInputStream。 期望子类使用修饰符“final”提供覆盖方法。
        参数
        obj - 要写入基础流的对象
        异常
        IOException - 如果在写入基础流时存在I / O错误
        从以下版本开始:
        1.2
        另请参见:
        ObjectOutputStream()writeObject(Object)
      • writeUnshared

        public void writeUnshared​(Object obj)
                           throws IOException
        将“非共享”对象写入ObjectOutputStream。 此方法与writeObject相同,只是它始终将给定对象写为流中的新唯一对象(而不是指向先前序列化实例的后引用)。 特别:
        • 通过writeUnshared写入的对象总是以与新出现的对象(尚未写入流的对象)相同的方式序列化,无论该对象是否先前已写入。
        • 如果writeObject用于编写先前使用writeUnshared编写的对象,则先前的writeUnshared操作将被视为写入单独的对象。 换句话说,ObjectOutputStream永远不会生成对通过调用writeUnshared写入的对象数据的反向引用。
        虽然通过writeUnshared编写对象本身并不保证在反序列化时对对象的唯一引用,但它允许在流中多次定义单个对象,因此接收器对readUnshared的多次调用不会发生冲突。 请注意,上述规则仅适用于使用writeUnshared编写的基础级对象,而不适用于要序列化的对象图中的任何可传递引用的子对象。

        覆盖此方法的ObjectOutputStream子类只能在拥有“enableSubclassImplementation”SerializablePermission的安全上下文中构造; 在没有此权限的情况下实例化此类子类的任何尝试都将导致抛出SecurityException。

        参数
        obj - 要写 obj对象
        异常
        NotSerializableException - 如果要序列化的图形中的对象未实现Serializable接口
        InvalidClassException - 如果要序列化的对象的类存在问题
        IOException - 如果序列化期间发生I / O错误
        从以下版本开始:
        1.4
      • defaultWriteObject

        public void defaultWriteObject()
                                throws IOException
        将当前类的非静态和非瞬态字段写入此流。 这可能只能从被序列化的类的writeObject方法调用。 如果以其他方式调用它,它将抛出NotActiveException。
        异常
        IOException - 如果在写入底层 OutputStream发生I / O错误
      • putFields

        public ObjectOutputStream.PutField putFields()
                                              throws IOException
        检索用于缓冲要写入流的持久字段的对象。 调用writeFields方法时,字段将写入流。
        结果
        包含可序列化字段的Putfield类的实例
        异常
        IOException - 如果发生I / O错误
        从以下版本开始:
        1.2
      • writeFields

        public void writeFields()
                         throws IOException
        将缓冲的字段写入流。
        异常
        IOException - 如果在写入基础流时发生I / O错误
        NotActiveException - 未调用类writeObject方法时调用以写入对象的状态。
        从以下版本开始:
        1.2
      • reset

        public void reset()
                   throws IOException
        重置将忽略已写入流的任何对象的状态。 状态重置为与新的ObjectOutputStream相同。 流中的当前点被标记为重置,因此相应的ObjectInputStream将在同一点重置。 先前写入流的对象将不会被称为已在流中。 它们将再次写入流中。
        异常
        IOException - 如果在序列化对象时调用reset()。
      • annotateClass

        protected void annotateClass​(<?> cl)
                              throws IOException
        子类可以实现此方法以允许类数据存储在流中。 默认情况下,此方法不执行任 ObjectInputStream中的对应方法是resolveClass。 对于流中的每个唯一类,此方法只调用一次。 类名和签名已经写入流中。 此方法可以自由使用ObjectOutputStream来保存它认为合适的类的任何表示(例如,类文件的字节)。 ObjectInputStream的相应子类中的resolveClass方法必须读取并使用由annotateClass编写的任何数据或对象。
        参数
        cl - 为其注释自定义数据的类
        异常
        IOException - 底层OutputStream抛出的任何异常。
      • annotateProxyClass

        protected void annotateProxyClass​(<?> cl)
                                   throws IOException
        子类可以实现此方法以将流中的自定义数据与动态代理类的描述符一起存储。

        对于流中的每个唯一代理类描述符,此方法只调用一次。 ObjectOutputStream中此方法的默认实现不执行任何操作。

        ObjectInputStream的相应方法是resolveProxyClass 对于覆盖此方法的给定子类ObjectOutputStream ,相应子类ObjectInputStreamresolveProxyClass方法必须读取annotateProxyClass写入的任何数据或对象。

        参数
        cl - 为其注释自定义数据的代理类
        异常
        IOException - 基础 OutputStream抛出的任何异常
        从以下版本开始:
        1.3
        另请参见:
        ObjectInputStream.resolveProxyClass(String[])
      • replaceObject

        protected Object replaceObject​(Object obj)
                                throws IOException
        此方法将允许ObjectOutputStream的受信任子类在序列化期间将一个对象替换为另一个对象。 在调用enableReplaceObject之前,将禁用替换对象。 enableReplaceObject方法检查请求进行替换的流是否可信。 写入序列化流的每个对象的第一次出现都传递给replaceObject。 对该对象的后续引用将由对replaceObject的原始调用返回的对象替换。 为确保不会无意中公开对象的私有状态,只有受信任的流可以使用replaceObject。

        ObjectOutputStream.writeObject方法接受Object类型的参数(与Serializable类型相反),以允许非可序列化对象被可序列化对象替换的情况。

        当子类替换对象时,它必须确保在反序列化期间必须进行互补替换,或者替换对象与将存储引用的每个字段兼容。 类型不是字段或数组元素类型的子类的对象通过引发异常来中止序列化,并且不存储该对象。

        首次遇到每个对象时,只调用一次此方法。 对该对象的所有后续引用都将重定向到新对象。 此方法应返回要替换的对象或原始对象。

        Null可以作为要替换的对象返回,但是可能会在包含对原始对象的引用的类中导致NullReferenceException,因为它们可能期望对象而不是null。

        参数
        obj - 要替换的对象
        结果
        替换指定的替换对象
        异常
        IOException - 底层OutputStream抛出的任何异常。
      • enableReplaceObject

        protected boolean enableReplaceObject​(boolean enable)
                                       throws SecurityException
        使流能够替换写入流的对象。 启用后,将为每个要序列化的对象调用replaceObject(java.lang.Object)方法。

        如果当前未启用对象替换,并且enable为true,并且安装了安全管理器,则此方法首先使用SerializablePermission("enableSubstitution")权限调用安全管理器的checkPermission方法,以确保允许调用者启用流来替换对象写入流。

        参数
        enable - 如果允许对每个被序列化的对象使用 replaceObjectenable true
        结果
        调用此方法之前的先前设置
        异常
        SecurityException - 如果存在安全管理器且其 checkPermission方法拒绝启用流来替换写入流的对象。
        另请参见:
        SecurityManager.checkPermission(java.security.Permission)SerializablePermission
      • writeStreamHeader

        protected void writeStreamHeader()
                                  throws IOException
        提供了writeStreamHeader方法,因此子类可以将自己的标头附加或预先添加到流中。 它将幻数和版本写入流。
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeClassDescriptor

        protected void writeClassDescriptor​(ObjectStreamClass desc)
                                     throws IOException
        将指定的类描述符写入ObjectOutputStream。 类描述符用于标识写入流的对象类。 ObjectOutputStream的子类可以重写此方法,以自定义类描述符写入序列化流的方式。 然后应该重写ObjectInputStream中的相应方法readClassDescriptor ,以从其自定义流表示重构类描述符。 默认情况下,此方法根据对象序列化规范中定义的格式写入类描述符。

        请注意,仅当ObjectOutputStream未使用旧的序列化流格式(通过调用ObjectOutputStream的useProtocolVersion方法设置)时, useProtocolVersion调用useProtocolVersion方法。 如果此序列化流使用旧格式( PROTOCOL_VERSION_1 ),则类描述符将以无法覆盖或自定义的方式在内部编写。

        参数
        desc - 要写 desc类描述符
        异常
        IOException - 如果发生I / O错误。
        从以下版本开始:
        1.3
        另请参见:
        ObjectInputStream.readClassDescriptor()useProtocolVersion(int)ObjectStreamConstants.PROTOCOL_VERSION_1
      • write

        public void write​(byte[] buf,
                          int off,
                          int len)
                   throws IOException
        写一个子字节数组。
        Specified by:
        write在界面 DataOutput
        Specified by:
        write ,界面 ObjectOutput
        重写:
        writeOutputStream
        参数
        buf - 要写入的数据
        off - 数据中的起始偏移量
        len - 写入的字节数
        异常
        IOException - 如果发生I / O错误。
      • drain

        protected void drain()
                      throws IOException
        排除ObjectOutputStream中的所有缓冲数据。 与flush类似,但不会将flush传播到底层流。
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeBoolean

        public void writeBoolean​(boolean val)
                          throws IOException
        写一个布尔值。
        Specified by:
        writeBoolean在界面 DataOutput
        参数
        val - 要写入的布尔值
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeByte

        public void writeByte​(int val)
                       throws IOException
        写一个8位字节。
        Specified by:
        writeByte在界面 DataOutput
        参数
        val - 要写入的字节值
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeShort

        public void writeShort​(int val)
                        throws IOException
        写一个16位的短。
        Specified by:
        writeShort在界面 DataOutput
        参数
        val - 要写入的短值
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeChar

        public void writeChar​(int val)
                       throws IOException
        写一个16位字符。
        Specified by:
        writeChar在界面 DataOutput
        参数
        val - 要写入的char值
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeInt

        public void writeInt​(int val)
                      throws IOException
        写一个32位的int。
        Specified by:
        writeInt在界面 DataOutput
        参数
        val - 要写入的整数值
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeLong

        public void writeLong​(long val)
                       throws IOException
        写入64位长。
        Specified by:
        writeLong在界面 DataOutput
        参数
        val - 要写入的长值
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeFloat

        public void writeFloat​(float val)
                        throws IOException
        写一个32位浮点数。
        Specified by:
        writeFloat in interface DataOutput
        参数
        val - 要写入的浮点值
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeDouble

        public void writeDouble​(double val)
                         throws IOException
        写一个64位双。
        Specified by:
        writeDouble ,界面 DataOutput
        参数
        val - 要写入的double值
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeBytes

        public void writeBytes​(String str)
                        throws IOException
        将String写为字节序列。
        Specified by:
        writeBytes在界面 DataOutput
        参数
        str - 要写入的字节串
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeChars

        public void writeChars​(String str)
                        throws IOException
        将String写为一系列字符。
        Specified by:
        writeChars ,界面 DataOutput
        参数
        str - 要写入的字符串
        异常
        IOException - 如果在写入基础流时发生I / O错误
      • writeUTF

        public void writeUTF​(String str)
                      throws IOException
        该字符串的原始数据以modified UTF-8格式写入。 请注意,将String作为基元数据或作为Object写入流中存在显着差异。 由writeObject编写的String实例最初作为String写入流中。 将来的writeObject()将对字符串的写入引用调用到流中。
        Specified by:
        writeUTF在界面 DataOutput
        参数
        str - 要写入的字符串
        异常
        IOException - if I/O errors occur while writing to the underlying stream