Module  java.base
软件包  java.io

Class ObjectInputStream

  • All Implemented Interfaces:
    CloseableDataInputObjectInputObjectStreamConstantsAutoCloseable


    public class ObjectInputStream
    extends InputStream
    implements ObjectInput, ObjectStreamConstants
    ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。

    ObjectOutputStream和ObjectInputStream可以分别为与FileOutputStream和FileInputStream一起使用的对象图提供持久性存储的应用程序。 ObjectInputStream用于恢复先前序列化的对象。 其他用途包括使用套接字流在主机之间传递对象,或者在远程通信系统中进行封送和解组参数和参数。

    ObjectInputStream确保从流中创建的图中的所有对象的类型与Java虚拟机中存在的类匹配。 根据需要使用标准机制加载类。

    只能从流中读取支持java.io.Serializable或java.io.Externalizable接口的对象。

    方法readObject用于从流中读取对象。 应使用Java的安全铸造来获得所需的类型。 在Java中,字符串和数组是对象,在序列化过程中被视为对象。 读取时,需要将其转换为预期类型。

    可以使用DataInput上的适当方法从流中读取原始数据类型。

    对象的默认反序列化机制将每个字段的内容恢复为写入时的值和类型。 声明为瞬态或静态的字段被反序列化过程忽略。 对其他对象的引用导致根据需要从流中读取这些对象。 使用参考共享机制正确恢复对象的图形。 反序列化时总是分配新对象,这样可以防止现有对象被覆盖。

    读取对象类似于运行新对象的构造函数。 为对象分配内存,并初始化为零(NULL)。 对非可序列化类调用无参数构造函数,然后从最接近java.lang.object的可序列化类开始,从串中还原可序列化类的字段,并使用对象最特定的类完成。

    例如从ObjectOutputStream中的示例中写入的流中读取:

      FileInputStream fis = new FileInputStream("t.tmp");
          ObjectInputStream ois = new ObjectInputStream(fis);
    
          int i = ois.readInt();
          String today = (String) ois.readObject();
          Date date = (Date) ois.readObject();
    
          ois.close(); 

    类通过实现java.io.Serializable或java.io.Externalizable接口来控制它们是如何序列化的。

    实现Serializable接口允许对象序列化保存和恢复对象的整个状态,并允许类在流被写入的时间和读取时间之间演变。 它自动遍历对象之间的引用,保存和恢复整个图形。

    在序列化和反序列化过程中需要特殊处理的可序列化类应实现以下方法:

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

    readObject方法负责使用通过相应的writeObject方法写入流的数据来读取和恢复其特定类的对象的状态。 该方法不需要关注属于其超类或子类的状态。 通过从ObjectInputStream读取各个字段的数据并对对象的相应字段进行分配来恢复状态。 DataInput支持读取原始数据类型。

    任何尝试读取超过相应writeObject方法写入的自定义数据边界的对象数据将导致使用eof字段值为true抛出OptionalDataException。 超过分配数据结束的非对象读取将以与指示流结尾相同的方式反映数据的结尾:Bytewise读取将返回-1作为字节读取或读取的字节数,并且原语读取将抛出EOFExceptions。 如果没有相应的writeObject方法,则默认序列化数据的结尾标记分配的数据的结尾。

    在readExternal方法中发出的原始和对象读取调用的行为方式相同 - 如果流已经位于由相应的writeExternal方法写入的数据的末尾,则对象读取会将可选数据异常与eof设置为true,Bytewise读取将返回-1,并且原始读取将抛出EOFExceptions。 请注意,这种行为对于使用旧的ObjectStreamConstants.PROTOCOL_VERSION_1协议编写的流不适用,其中由writeExternal方法写入的数据的结尾未划分,因此无法检测。

    如果序列化流未将给定类列为反序列化对象的超类,则readObjectNoData方法负责初始化其特定类的对象的状态。 这可能发生在接收方使用与发送方不同的反序列化实例的类的版本的情况下,并且接收者的版本扩展了不被发送者版本扩展的类。 如果序列化流已被篡改,也可能发生这种情况; 因此,尽管存在“敌对”或不完整的源流,readObjectNoData可用于正确初始化反序列化对象。

    序列化不会读取或赋值任何不实现java.io.Serializable接口的对象的值。 不可序列化的对象的子类可以是可序列化的。 在这种情况下,非可序列化类必须有一个无参数构造函数,以允许其字段被初始化。 在这种情况下,子类有责任保存并恢复不可序列化类的状态。 通常情况下,该类的字段是可访问的(public,package或protected),或者可以使用get和set方法来恢复状态。

    可以在反序列化期间过滤流的内容。 如果filter is set上的ObjectInputStream的,所述ObjectInputFilter可以检查类,阵列的长度,在流,深度和数量从输入流消耗的字节的参考数是允许的,如果没有,可以终止反序列化。 A process-wide filter可以配置为应用于每个ObjectInputStream除非使用setObjectInputFilter替换。

    反序列化对象时发生的任何异常都将被ObjectInputStream捕获并中止读取过程。

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

    枚举常数的反序列化与普通可序列化或外部化对象不同。 枚举常数的序列化形式仅由其名称组成; 不传输常数的字段值。 要反序列化枚举常量,ObjectInputStream从流中读取常量名称; 然后通过调用具有枚举常量的基本类型和接收的常量名称作为参数的静态方法Enum.valueOf(Class, String)获得反序列化常数。 像其他可序列化或可外部化的对象一样,枚举常量可以用作序列化流中随后出现的反向引用的目标。 枚举常量被反序列化的过程无法自定义:在反序列化期间将忽略由枚举类型定义的任何特定于类的readObject,readObjectNoData和readResolve方法。 类似地,任何serialPersistentFields或serialVersionUID字段声明也被忽略 - 所有枚举类型都有一个固定的serialVersionUID为0L。

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

      • ObjectInputStream

        public ObjectInputStream​(InputStream in)
                          throws IOException
        创建从指定的InputStream读取的ObjectInputStream。 从流中读取序列化流头并进行验证。 该构造函数将阻塞,直到相应的ObjectOutputStream已写入并刷新标题。

        序列化过滤器初始化为值the process-wide filter

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

        参数
        in - 要读取的输入流
        异常
        StreamCorruptedException - 如果流标题不正确
        IOException - 如果在读取流标题时发生I / O错误
        SecurityException - 如果不可信子类非法覆盖安全敏感方法
        NullPointerException - 如果 innull
        另请参见:
        ObjectInputStream()readFields()ObjectOutputStream(OutputStream)
    • 方法详细信息

      • readObject

        public final Object readObject​()
                                throws IOException,
                                       ClassNotFoundException
        从ObjectInputStream读取一个对象。 读取对象的类,类的签名以及类的非瞬态和非静态字段的值以及其所有超类型。 可以使用writeObject和readObject方法覆盖类的默认反序列化。 这个对象引用的对象被传递性地读取,以便通过readObject重构一个完整的对象图。

        当其所有字段及其引用的对象完全还原时,根对象将被完全还原。 此时,对象验证回调按照它们注册的优先级顺序执行。 回调由对象(在readObject特殊方法中)注册,因为它们被单独还原。

        序列化过滤器(不是null )被调用为每个对象(常规或类)读取重建根对象。 详见setObjectInputFilter

        对于InputStream和不应反序列化的类的问题,抛出异常。 所有异常都是对InputStream致命的,并将其置于不确定状态; 呼叫者可以忽略或恢复流状态。

        Specified by:
        readObject在接口 ObjectInput
        结果
        该对象从流中读取
        异常
        ClassNotFoundException - 无法找到序列化对象的类。
        InvalidClassException - 序列化使用的类错误。
        StreamCorruptedException - 流中的控制信息不一致。
        OptionalDataException - 在流中找到原始数据,而不是对象。
        IOException - 任何常见的输入/输出相关异常。
      • readObjectOverride

        protected Object readObjectOverride​()
                                     throws IOException,
                                            ClassNotFoundException
        此方法由ObjectOutputStream的受信任子类调用,该子类使用受保护的无参构造函数构造ObjectOutputStream。 该子类预计将提供一个具有修饰符“final”的覆盖方法。
        结果
        对象从流中读取。
        异常
        ClassNotFoundException - 无法找到序列化对象的类定义。
        OptionalDataException - 在流中找到原始数据,而不是对象。
        IOException - 如果从底层流读取时发生I / O错误
        从以下版本开始:
        1.2
        另请参见:
        ObjectInputStream()readObject()
      • readUnshared

        public Object readUnshared​()
                            throws IOException,
                                   ClassNotFoundException
        从ObjectInputStream读取一个“非共享”对象。 此方法与readObject相同,只是它阻止对readObject的后续调用和readUnshared返回对通过此调用获取的反序列化实例的其他引用。 特别:
        • 如果调用readUnshared来反序列化一个反向引用(以前已经写入流的对象的流表示),则抛出ObjectStreamException。
        • 如果readUnshared成功返回,则随后尝试反序列化对readUnshared反序列化的流处理的反向引用将导致抛出ObjectStreamException。
        通过readUnshared对对象进行反序列化将使与返回对象关联的流句柄无效。 请注意,这本身并不总是保证readUnshared返回的引用是唯一的; 反序列化对象可以定义一个readResolve方法,该方法返回对其他方可见的对象,或者readUnshared可以返回在流中或通过外部方式在其他地方可获取的Class对象或枚举常量。 如果反序列化对象定义了一个readResolve方法,并且该方法的调用返回一个数组,那么readUnshared返回该数组的浅克隆; 这样可以保证返回的数组对象是唯一的,即使在底层数据流已经被处理的情况下,也不能再从调用readObject或readUnshared在ObjectInputStream上获得。

        序列化过滤器(不是null )被调用为每个对象(常规或类)读取重建根对象。 详见setObjectInputFilter

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

        结果
        参考反序列化对象
        异常
        ClassNotFoundException - 如果无法找到反序列化对象的类
        StreamCorruptedException - 如果流中的控制信息不一致
        ObjectStreamException - 如果反序列化对象已经出现在流中
        OptionalDataException - 如果原始数据是下一个流
        IOException - 如果在反序列化期间发生I / O错误
        从以下版本开始:
        1.4
      • defaultReadObject

        public void defaultReadObject​()
                               throws IOException,
                                      ClassNotFoundException
        从此流读取当前类的非静态和非瞬态字段。 这只能从被反序列化的类的readObject方法调用。 否则将抛出NotActiveException异常。
        异常
        ClassNotFoundException - 如果找不到序列化对象的类。
        IOException - 如果发生I / O错误。
        NotActiveException - 如果流当前未读取对象。
      • registerValidation

        public void registerValidation​(ObjectInputValidation obj,
                                       int prio)
                                throws NotActiveException,
                                       InvalidObjectException
        在返回图之前注册要验证的对象。 虽然类似于resolveObject这些验证在整个图形重新构建之后被调用。 通常,readObject方法将使用流注册对象,以便当所有对象都被还原时,可以执行最后一组验证。
        参数
        obj - 接收验证回调的对象。
        prio - 控制回调的顺序;零是一个很好的默认值。 使用较高的数字可以提前回调,较低的数字可用于以后的回调。 在优先级中,回调按照特定顺序进行处理。
        异常
        NotActiveException - 流当前未读取对象,因此无法注册回调。
        InvalidObjectException - 验证对象为null。
      • resolveClass

        protected Class<?> resolveClass​(ObjectStreamClass desc)
                                 throws IOException,
                                        ClassNotFoundException
        加载本地类等效的指定流类描述。 子类可以实现此方法,以允许从备用源获取类。

        ObjectOutputStream的相应方法为annotateClass 对于流中的每个唯一类,此方法将仅调用一次。 该方法可以由子类实现,以使用备用加载机制,但必须返回一个Class对象。 一旦返回,如果类不是数组类,其serialVersionUID与序列化类的serialVersionUID进行比较,如果不匹配,则反序列化失败,并抛出一个InvalidClassException

        该方法的默认实现在ObjectInputStream返回调用结果

          Class.forName(desc.getName(), false, loader) 
        其中loader是当前线程的堆栈(从当前执行的方法开始)的第一个类加载器,既不是platform class loader也不是其祖先; 否则, loader平台类加载器 如果在此调用结果ClassNotFoundException和传递的名称ObjectStreamClass实例的基本类型或void Java语言的关键字,那么Class表示基本类型或void对象将被退回(例如, ObjectStreamClass名称为"int"会解决到Integer.TYPE )。 否则,将向该方法的调用者抛出ClassNotFoundException
        参数
        desc - 类 ObjectStreamClass一个实例
        结果
        一个 Class对象对应 desc
        异常
        IOException - 任何通常的输入/输出异常。
        ClassNotFoundException - 如果无法找到序列化对象的类。
      • resolveProxyClass

        protected Class<?> resolveProxyClass​(String[] interfaces)
                                      throws IOException,
                                             ClassNotFoundException
        返回一个代理类,它实现代理类描述符中命名的接口; 子类可以实现此方法从流中读取自定义数据以及动态代理类的描述符,从而允许它们为接口和代理类使用备用加载机制。

        对于流中的每个唯一代理类描述符,该方法被称为一次。

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

        这种方法的默认实现ObjectInputStream返回调用的结果Proxy.getProxyClass与列表Class对象为在指定接口interfaces参数。 每个接口名称iClass对象是通过调用返回的值

          Class.forName(i, false, loader) 
        其中loader是当前线程的堆栈(从当前执行的方法开始)中的第一个类加载器,既不是platform class loader也不是其祖先; 否则, loader平台类加载器 除非任何解析的界面都是非公开的,否则同样的值为loader也是类加载器传递给Proxy.getProxyClass ; 如果存在非公共接口,则会传递其类加载器(如果遇到多个非公共接口类加载器,则抛出一个IllegalAccessError )。 如果Proxy.getProxyClass抛出IllegalArgumentExceptionresolveProxyClass将抛出ClassNotFoundException包含IllegalArgumentException
        参数
        interfaces - 代理类描述符中反序列化的接口名称列表
        结果
        指定接口的代理类
        异常
        IOException - 底层 InputStream抛出的任何异常
        ClassNotFoundException - 如果无法找到代理类或任何命名的接口
        从以下版本开始:
        1.3
        另请参见:
        ObjectOutputStream.annotateProxyClass(Class)
      • resolveObject

        protected Object resolveObject​(Object obj)
                                throws IOException
        此方法将允许ObjectInputStream的受信任子类在反序列化期间将一个对象替换为另一个对象。 在调用enableResolveObject之前,将禁用替换对象。 enableResolveObject方法检查请求解析对象的流可以被信任。 对可序列化对象的每个引用都传递给resolveObject。 为了确保对象的私有状态不会被无意地暴露,只有信任的流可能使用resolveObject。

        在读取对象之后,在从readObject返回之前调用此方法。 默认的resolveObject方法只返回相同的对象。

        当子类替换对象时,必须确保替换对象与引用将被存储的每个字段兼容。 类型不是字段或数组元素类型的子类的对象通过引发异常终止序列化,并且不存储该对象。

        当首次遇到每个对象时,此方法仅调用一次。 对对象的所有后续引用将被重定向到新对象。

        参数
        obj - 要替代的对象
        结果
        替代对象
        异常
        IOException - 任何通常的输入/输出异常。
      • enableResolveObject

        protected boolean enableResolveObject​(boolean enable)
                                       throws SecurityException
        启用流来替换从流读取的对象。 启用时,为反序列化的每个对象调用resolveObject(java.lang.Object)方法。

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

        参数
        enable - 为每个被反序列化的对象使能 resolveObject
        结果
        此方法被调用之前的前一个设置
        异常
        SecurityException - 如果安全管理器存在,并且其 checkPermission方法拒绝使流能够更新从流读取的对象。
        另请参见:
        SecurityManager.checkPermission(java.security.Permission)SerializablePermission
      • readStreamHeader

        protected void readStreamHeader​()
                                 throws IOException,
                                        StreamCorruptedException
        提供了readStreamHeader方法来允许子类读取和验证自己的流标题。 它读取和验证魔术数字和版本号。
        异常
        IOException - 如果从基础 InputStream读取时存在I / O错误
        StreamCorruptedException - 如果流中的控制信息不一致
      • readClassDescriptor

        protected ObjectStreamClass readClassDescriptor​()
                                                 throws IOException,
                                                        ClassNotFoundException
        从序列化流读取类描述符。 当ObjectInputStream期望类描述符作为序列化流中的下一个项时,调用此方法。 ObjectInputStream的子类可以覆盖此方法以读取已经以非标准格式(由ObjectOutputStream的子类覆盖了writeClassDescriptor方法)的类描述符。 默认情况下,此方法根据对象序列化规范中定义的格式读取类描述符。
        结果
        类描述符读取
        异常
        IOException - 如果发生I / O错误。
        ClassNotFoundException - 如果找不到类描述符表示中使用的序列化对象的类
        从以下版本开始:
        1.3
        另请参见:
        ObjectOutputStream.writeClassDescriptor(java.io.ObjectStreamClass)
      • read

        public int read​()
                 throws IOException
        读取一个字节的数据。 如果没有输入可用,此方法将阻止。
        Specified by:
        read在接口 ObjectInput
        Specified by:
        readInputStream
        结果
        读取字节,如果达到流的结尾,则返回-1。
        异常
        IOException - 如果发生I / O错误。
      • read

        public int read​(byte[] buf,
                        int off,
                        int len)
                 throws IOException
        读入一个字节数组。 该方法将阻塞,直到有些输入可用。 考虑使用java.io.DataInputStream.readFully来读取“length”字节。
        Specified by:
        read在接口 ObjectInput
        重写:
        read中的 InputStream
        参数
        buf - 读取数据的缓冲区
        off - 目标数组 buf的起始偏移量
        len - 读取的最大字节数
        结果
        读取的实际字节数,到达流结束时返回-1。
        异常
        NullPointerException - 如果 bufnull
        IndexOutOfBoundsException - 如果 off为负数,则 len为负数,或 len大于 buf.length - off
        IOException - 如果发生I / O错误。
        另请参见:
        DataInputStream.readFully(byte[],int,int)
      • readFully

        public void readFully​(byte[] buf,
                              int off,
                              int len)
                       throws IOException
        读取字节,阻塞直到读取所有字节。
        Specified by:
        readFully在接口 DataInput
        参数
        buf - 读取数据的缓冲区
        off - 数据阵列的起始偏移量 buf
        len - 要读取的最大字节数
        异常
        NullPointerException - 如果 bufnull
        IndexOutOfBoundsException - 如果 off为负, len ,否则为 len ,大于 buf.length - off
        EOFException - 如果达到文件结尾。
        IOException - 如果发生其他I / O错误。
      • skipBytes

        public int skipBytes​(int len)
                      throws IOException
        跳过字节。
        Specified by:
        skipBytes在接口 DataInput
        参数
        len - 要跳过的字节数
        结果
        实际跳过的字节数。
        异常
        IOException - 如果发生I / O错误。
      • readLine

        @Deprecated
        public String readLine​()
                        throws IOException
        已过时。 此方法无法将字节正确转换为字符。 有关详细信息和替代方案,请参阅DataInputStream。
        在\ n,\ r,\ r \ n或EOF终止的行中读取。
        Specified by:
        readLine在接口 DataInput
        结果
        一行的字符串副本。
        异常
        IOException - 如果从底层 InputStream读取时存在I / O错误
      • setObjectInputFilter

        public final void setObjectInputFilter​(ObjectInputFilter filter)
        为流设置序列化过滤器。 为流中的每个类和引用调用过滤器的checkInput方法。 过滤器可以检查任何或所有类,数组长度,引用数量,图形的深度和输入流的大小。 深度是嵌套readObject调用的次数,从读取正在反序列化的图的根和当前对象被反序列化开始。 引用的数量是对象的累积数量和对已经从流中读取的对象的引用,包括正在读取的当前对象。 只有从流中读取对象而不是原语时,才会调用该过滤器。

        如果过滤器返回Status.REJECTEDnull或抛出一个RuntimeException ,主动readObject或者readUnshared抛出InvalidClassException ,否则反序列化不间断地继续。

        序列化过滤器被初始化为值ObjectInputFilter.Config.getSerialFilterObjectInputStream被构造和只能进行一次设置为自定义过滤器。

        实现要求:
        readObjectreadUnshared为流中的每个对象(常规或类)调用过滤器(不是null )。 字符串被视为原语,不调用过滤器。 调用过滤器:
        • 每个对象引用以前从流中反序列化(类为null ,arrayLength为-1)
        • 每个常规类(类不是null ,arrayLength是-1)
        • 每个接口的动态代理和动态代理类本身(类不是null ,arrayLength是-1)
        • 每个数组使用数组类型和数组长度进行过滤(类是数组类型,arrayLength是请求的长度)
        • 每个对象被替换为其类' readResolve方法的是使用替换对象的类进行过滤,如果不是null ,而如果它是一个数组,则arrayLength,否则为-1,
        • 并且使用替换对象的类来过滤使用resolveObject每个对象,如果不是null ,如果它是一个数组,则arrayLength,否则为-1。
        当调用checkInput方法时,可以访问当前类,数组长度,已从流中读取的当前引用数目,嵌套调用深度为readObjectreadUnshared ,以及实现依赖于从输入流。

        每次调用readObjectreadUnshared在读取对象之前将深度增加1,并在正常或异常返回之前减少1。 深度开始于1并且每个嵌套对象的增加量和每个嵌套调用返回时递减。 流中的引用数开始于1并在读取对象之前增加。

        参数
        filter - 过滤器可能为null
        异常
        SecurityException - 如果有安全管理员,并且没有授予 SerializablePermission("serialFilter")
        IllegalStateException - 如果 current filter不是 null并且不是进程范围的过滤器
        从以下版本开始:
        9