Module  java.base
软件包  java.io

Class ObjectOutputStream

  • All Implemented Interfaces:
    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接口的对象的字段。 不可序列化的对象的子类可以是可序列化的。 在这种情况下,非可序列化类必须有一个无参数构造函数,以允许其字段被初始化。 在这种情况下,子类有责任保存并恢复不可序列化类的状态。 通常情况下,该类的字段是可访问的(public,package或protected),或者可以使用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的构造函数不会阻塞。

        如果安装了一个安全管理器,那么这个构造函数会在被覆盖ObjectOutputStream.putFields或ObjectOutputStream.writeUnshared方法的子类的构造函数直接或间接调用时检查“enableSubclassImplementation”SerializablePermission。

        参数
        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是致命的,它将处于不确定状态,由呼叫者来忽略或恢复流状态。

        Specified by:
        writeObject在接口 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​(Class<?> cl)
                              throws IOException
        子类可以实现此方法,以允许类数据存储在流中。 默认情况下,此方法什么都不做 ObjectInputStream中的相应方法是resolveClass。 对于流中的每个唯一类,此方法称为一次。 类名和签名已经写入流。 该方法可以免费使用ObjectOutputStream来保存其认为合适的类的任何表示(例如,类文件的字节)。 ObjectInputStream对应子类中的resolveClass方法必须读取并使用annotateClass写入的任何数据或对象。
        参数
        cl - 为自定义数据注释的类
        异常
        IOException - 底层OutputStream抛出的任何异常。
      • annotateProxyClass

        protected void annotateProxyClass​(Class<?> cl)
                                   throws IOException
        子类可以实现这种方法来存储流中的自定义数据以及动态代理类的描述符。

        对于流中的每个唯一代理类描述符,该方法被称为一次。 这个方法的默认实现在ObjectOutputStream中什么都不做。

        ObjectInputStream的相应方法为resolveProxyClass 对于覆盖此方法的resolveProxyClass的给定子类, ObjectOutputStream的相应子类中的ObjectInputStream必须读取由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是真实的,并且安装了安全管理器,此方法首先调用安全管理器的checkPermission方法与SerializablePermission("enableSubstitution")权限,以确保调用者被允许使流对象进行替换的写入流。

        参数
        enable - 允许对串行化的每个对象使用 replaceObject
        结果
        此方法被调用之前的前一个设置
        异常
        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的相应方法, readClassDescriptor从其自定义流表示中重新构建类描述符。 默认情况下,此方法根据对象序列化规范中定义的格式编写类描述符。

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

        参数
        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 - 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 - val的长的价值
        异常
        IOException - 如果在写入底层流时发生I / O错误
      • writeFloat

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

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

        public void writeBytes​(String str)
                        throws IOException
        写一个字符串作为字节序列。
        Specified by:
        writeBytes在接口 DataOutput
        参数
        str - 要写入的字节串
        异常
        IOException - 如果在写入底层流时发生I / O错误
      • writeChars

        public void writeChars​(String str)
                        throws IOException
        写一个字符串作为一系列的字符。
        Specified by:
        writeChars在接口 DataOutput
        参数
        str - 要写入的字符串
        异常
        IOException - 如果在写入底层流时发生I / O错误
      • writeUTF

        public void writeUTF​(String str)
                      throws IOException
        此字符串的原始数据写入格式为modified UTF-8 请注意,将字符串写入流中作为原始数据或作为对象有重大差异。 由writeObject写的String实例最初作为String写入流中。 未来的writeObject()会将对字符串的引用调用到流中。
        Specified by:
        writeUTF在接口 DataOutput
        参数
        str - 要写入的字符串
        异常
        IOException - if I/O errors occur while writing to the underlying stream