public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants
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方法来恢复状态。
反序列化对象时发生的任何异常都将被ObjectInputStream捕获并中止读取过程。
实现Externalizable接口允许对象完全控制对象的序列化表单的内容和格式。 调用Externalizable接口writeExternal和readExternal的方法来保存和恢复对象的状态。 当由类实现时,他们可以使用ObjectOutput和ObjectInput的所有方法来写入和读取自己的状态。 对象处理发生的任何版本控制都是有责任的。
枚举常数的反序列化与普通可序列化或外部化对象不同。 枚举常数的序列化形式仅由其名称组成; 不传输常数的字段值。 要反序列化枚举常量,ObjectInputStream从流中读取常量名称; 然后通过使用枚举常量的基本类型和接收的常量名称作为参数调用静态方法Enum.valueOf(Class, String)
获得反序列化常数。 像其他可序列化或可外部化的对象一样,枚举常量可以作为随后在序列化流中出现的反向引用的目标。 枚举常量被反序列化的过程无法自定义:在反序列化期间将忽略由枚举类型定义的任何特定于类的readObject,readObjectNoData和readResolve方法。 类似地,任何serialPersistentFields或serialVersionUID字段声明也被忽略 - 所有枚举类型都有一个固定的serialVersionUID为0L。
DataInput
, ObjectOutputStream
, Serializable
, Object Serialization Specification, Section 3, Object Input Classes
Modifier and Type | Class and Description |
---|---|
static class |
ObjectInputStream.GetField
提供对从输入流读取的持久性字段的访问。
|
baseWireHandle, PROTOCOL_VERSION_1, PROTOCOL_VERSION_2, SC_BLOCK_DATA, SC_ENUM, SC_EXTERNALIZABLE, SC_SERIALIZABLE, SC_WRITE_METHOD, STREAM_MAGIC, STREAM_VERSION, SUBCLASS_IMPLEMENTATION_PERMISSION, SUBSTITUTION_PERMISSION, TC_ARRAY, TC_BASE, TC_BLOCKDATA, TC_BLOCKDATALONG, TC_CLASS, TC_CLASSDESC, TC_ENDBLOCKDATA, TC_ENUM, TC_EXCEPTION, TC_LONGSTRING, TC_MAX, TC_NULL, TC_OBJECT, TC_PROXYCLASSDESC, TC_REFERENCE, TC_RESET, TC_STRING
Modifier | Constructor and Description |
---|---|
protected |
ObjectInputStream()
为完全重新实现ObjectInputStream的子类提供一种方法,不必分配刚刚被ObjectInputStream实现使用的私有数据。
|
|
ObjectInputStream(InputStream in)
创建从指定的InputStream读取的ObjectInputStream。
|
Modifier and Type | Method and Description |
---|---|
int |
available()
返回可以读取而不阻塞的字节数。
|
void |
close()
关闭输入流。
|
void |
defaultReadObject()
从此流读取当前类的非静态和非瞬态字段。
|
protected boolean |
enableResolveObject(boolean enable)
启用流以允许从流中读取的对象被替换。
|
int |
read()
读取一个字节的数据。
|
int |
read(byte[] buf, int off, int len)
读入一个字节数组。
|
boolean |
readBoolean()
读取布尔值。
|
byte |
readByte()
读取一个8位字节。
|
char |
readChar()
读一个16位字符。
|
protected ObjectStreamClass |
readClassDescriptor()
从序列化流读取类描述符。
|
double |
readDouble()
读64位双倍。
|
ObjectInputStream.GetField |
readFields()
从流中读取持久性字段,并通过名称获取它们。
|
float |
readFloat()
读32位浮点数。
|
void |
readFully(byte[] buf)
读取字节,阻塞直到读取所有字节。
|
void |
readFully(byte[] buf, int off, int len)
读取字节,阻塞直到读取所有字节。
|
int |
readInt()
读取一个32位int。
|
String |
readLine()
已弃用
此方法无法将字节正确转换为字符。
有关详细信息和替代方案,请参阅DataInputStream。
|
long |
readLong()
读64位长。
|
Object |
readObject()
从ObjectInputStream读取一个对象。
|
protected Object |
readObjectOverride()
此方法由ObjectOutputStream的受信任子类调用,该子类使用受保护的无参构造函数构造ObjectOutputStream。
|
short |
readShort()
读取16位短。
|
protected void |
readStreamHeader()
提供了readStreamHeader方法来允许子类读取和验证自己的流标题。
|
Object |
readUnshared()
从ObjectInputStream读取一个“非共享”对象。
|
int |
readUnsignedByte()
读取一个无符号的8位字节。
|
int |
readUnsignedShort()
读取无符号16位短。
|
String |
readUTF()
以
modified UTF-8格式读取字符串。
|
void |
registerValidation(ObjectInputValidation obj, int prio)
在返回图之前注册要验证的对象。
|
protected 类<?> |
resolveClass(ObjectStreamClass desc)
加载本地类等效的指定流类描述。
|
protected Object |
resolveObject(Object obj)
此方法将允许ObjectInputStream的受信任子类在反序列化期间将一个对象替换为另一个对象。
|
protected 类<?> |
resolveProxyClass(String[] interfaces)
返回一个代理类,它实现代理类描述符中命名的接口;
子类可以实现此方法从流中读取自定义数据以及动态代理类的描述符,从而允许它们为接口和代理类使用备用加载机制。
|
int |
skipBytes(int len)
跳过字节。
|
mark, markSupported, read, reset, skip
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
read, skip
public ObjectInputStream(InputStream in) throws IOException
如果安装了一个安全管理器,那么这个构造函数将会在覆盖ObjectInputStream.readFields或ObjectInputStream.readUnshared方法的子类的构造函数直接或间接调用时检查“enableSubclassImplementation”SerializablePermission。
in
- 要读取的输入流
StreamCorruptedException
- 如果流标题不正确
IOException
- 如果在读取流标题时发生I / O错误
SecurityException
- 如果不可信子类非法覆盖安全敏感方法
NullPointerException
- 如果
in
是
null
ObjectInputStream()
,
readFields()
,
ObjectOutputStream.ObjectOutputStream(OutputStream)
protected ObjectInputStream() throws IOException, SecurityException
如果安装了安全管理器,则此方法首先使用SerializablePermission("enableSubclassImplementation")
权限调用安全管理器的checkPermission
方法,以确保启用子类化。
SecurityException
- 如果安全管理器存在,并且其
checkPermission
方法拒绝启用子类化。
IOException
- 如果在创建此流时发生I / O错误
SecurityManager.checkPermission(java.security.Permission)
, SerializablePermission
public final Object readObject() throws IOException, ClassNotFoundException
当其所有字段及其引用的对象完全还原时,根对象将被完全还原。 此时,对象验证回调按照它们注册的优先级顺序执行。 回调由对象(在readObject特殊方法中)注册,因为它们被单独还原。
对于InputStream和不应反序列化的类的问题,抛出异常。 所有异常都是对InputStream致命的,并将其置于不确定状态; 呼叫者可以忽略或恢复流状态。
readObject
在界面
ObjectInput
ClassNotFoundException
- 无法找到序列化对象的类。
InvalidClassException
- 序列化使用的类错误。
StreamCorruptedException
- 流中的控制信息不一致。
OptionalDataException
- 在流中找到原始数据,而不是对象。
IOException
- 任何常见的输入/输出相关异常。
protected Object readObjectOverride() throws IOException, ClassNotFoundException
ClassNotFoundException
- 无法找到序列化对象的类定义。
OptionalDataException
- 在流中找到原始数据,而不是对象。
IOException
- 如果从底层流读取I / O错误
ObjectInputStream()
,
readObject()
public Object readUnshared() throws IOException, ClassNotFoundException
覆盖此方法的ObjectInputStream子类只能在拥有“enableSubclassImplementation”SerializablePermission的安全上下文中构建; 任何尝试在没有此权限的情况下实例化此类子类将导致抛出SecurityException。
ClassNotFoundException
- 如果无法找到反序列化对象的类
StreamCorruptedException
- 如果流中的控制信息不一致
ObjectStreamException
- 如果
ObjectStreamException
化对象已经出现在流中
OptionalDataException
- 如果原始数据是下一个流
IOException
- 如果在反序列化期间发生I / O错误
public void defaultReadObject() throws IOException, ClassNotFoundException
ClassNotFoundException
- 如果无法找到序列化对象的类。
IOException
- 如果发生I / O错误。
NotActiveException
- 如果流当前未读取对象。
public ObjectInputStream.GetField readFields() throws IOException, ClassNotFoundException
GetField
对象表示反序列
GetField
对象的持久字段
ClassNotFoundException
- 如果无法找到序列化对象的类。
IOException
- 如果发生I / O错误。
NotActiveException
- 如果流当前未读取对象。
public void registerValidation(ObjectInputValidation obj, int prio) throws NotActiveException, InvalidObjectException
obj
- 接收验证回调的对象。
prio
- 控制prio
的顺序;零是一个很好的默认值。
使用较高的数字可以提前回调,较低的数字可用于以后的回调。
在优先级中,回调按照特定顺序进行处理。
NotActiveException
- 流当前未读取对象,因此无法注册回调。
InvalidObjectException
- 验证对象为null。
protected 类<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException
在相应的方法ObjectOutputStream
是annotateClass
。 对于流中的每个唯一类,此方法将仅调用一次。 这个方法可以通过子类来实现,使用一个备用的加载机制,但必须返回一个类
对象。 一旦返回,如果类不是数组类,其serialVersionUID与序列化类的serialVersionUID进行比较,如果不匹配,则反序列化失败,并抛出InvalidClassException
。
在此方法的默认实现ObjectInputStream
返回调用的结果
Class.forName(desc.getName(), false, loader)
其中loader
的确定如下:如果当前线程的堆栈中有一个方法,其声明类是由用户定义的类加载器定义的(并且不是为了实现反射调用而生成的),则loader
是对应于最接近的类加载器的类加载器这种方法到当前执行的帧;
否则, loader
是null
。
如果该调用导致ClassNotFoundException
和传递的名称ObjectStreamClass
是一个基本类型或void Java语言的关键字,那么实例类
表示基本类型或void对象将被退回(例如, ObjectStreamClass
名为"int"
会解决到Integer.TYPE
)。
否则, ClassNotFoundException
将被抛出这个方法的调用者。
desc
-
ObjectStreamClass
类的实例
类
对象对应于
desc
IOException
- 任何通常的输入/输出异常。
ClassNotFoundException
- 如果无法找到序列化对象的类。
protected 类<?> resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException
对于流中的每个唯一代理类描述符,该方法被称为一次。
在相应的方法ObjectOutputStream
是annotateProxyClass
。 对于给定的子类ObjectInputStream
重写该方法中, annotateProxyClass
中的相应子类方法ObjectOutputStream
必须写由该方法读取的任何数据或对象。
这种方法的默认实现ObjectInputStream
返回调用的结果Proxy.getProxyClass
与列表类
对象为在指定接口interfaces
参数。 每个接口名称i
的类
对象是通过调用返回的值
Class.forName(i, false, loader)
其中loader
是第一个非null
类加载器的执行堆栈,或null
如果没有非null
类加载器在堆栈( resolveClass
方法使用相同的类加载器选择)。
除非任何解析的界面是非公开的,否则同样的值loader
也是类加载器传递给Proxy.getProxyClass
;
如果存在非公共接口,则会传递其类加载器(如果遇到多个非公共接口类加载器,则抛出IllegalAccessError
)。
如果Proxy.getProxyClass
抛出IllegalArgumentException
, resolveProxyClass
将抛出一个ClassNotFoundException
包含IllegalArgumentException
。
interfaces
- 在代理类描述符中反序列化的接口名称列表
IOException
-由底层抛出的任何异常
InputStream
ClassNotFoundException
- 如果无法找到代理类或任何命名接口
ObjectOutputStream.annotateProxyClass(Class)
protected Object resolveObject(Object obj) throws IOException
在读取对象之后,在从readObject返回之前调用此方法。 默认的resolveObject方法只返回相同的对象。
当子类替换对象时,必须确保替换对象与引用将被存储的每个字段兼容。 类型不是字段或数组元素类型的子类的对象通过引发异常终止序列化,并且不存储该对象。
当首次遇到每个对象时,此方法仅调用一次。 对对象的所有后续引用将被重定向到新对象。
obj
- 要替代的对象
IOException
- 任何通常的输入/输出异常。
protected boolean enableResolveObject(boolean enable) throws SecurityException
如果enable为真,并且安装了一个安全管理器,则该方法首先使用SerializablePermission("enableSubstitution")
权限调用安全管理器的checkPermission
方法,以确保启用流允许从流中读取的对象被替换。
enable
-真正的能够使用的
resolveObject
为每个对象反序列化
SecurityException
- 如果安全管理器存在,并且其
checkPermission
方法拒绝启用流,以允许从流中读取的对象被替换。
SecurityManager.checkPermission(java.security.Permission)
, SerializablePermission
protected void readStreamHeader() throws IOException, StreamCorruptedException
IOException
- 从底层
InputStream
读取时是否存在I / O错误
StreamCorruptedException
- 如果流中的控制信息不一致
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException
writeClassDescriptor
方法)的类writeClassDescriptor
。
默认情况下,此方法根据对象序列化规范中定义的格式读取类描述符。
IOException
- 如果发生I / O错误。
ClassNotFoundException
- 如果找不到类描述符表示中使用的序列化对象的类
ObjectOutputStream.writeClassDescriptor(java.io.ObjectStreamClass)
public int read() throws IOException
read
在界面
ObjectInput
read
在类别
InputStream
IOException
- 如果发生I / O错误。
public int read(byte[] buf, int off, int len) throws IOException
read
在界面
ObjectInput
read
在类别
InputStream
buf
- 读取数据的缓冲区
off
- 数据的起始偏移量
len
- 读取的最大字节数
IOException
- 如果发生I / O错误。
DataInputStream.readFully(byte[],int,int)
public int available() throws IOException
available
在界面
ObjectInput
available
在
InputStream
IOException
- 从底层
InputStream
读取时是否存在I / O错误
public void close() throws IOException
close
在接口
Closeable
close
在接口
ObjectInput
close
在接口
AutoCloseable
close
在类别
InputStream
IOException
- 如果发生I / O错误。
public boolean readBoolean() throws IOException
readBoolean
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public byte readByte() throws IOException
readByte
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public int readUnsignedByte() throws IOException
readUnsignedByte
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public char readChar() throws IOException
readChar
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public short readShort() throws IOException
readShort
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public int readUnsignedShort() throws IOException
readUnsignedShort
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public int readInt() throws IOException
readInt
在接口
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public long readLong() throws IOException
readLong
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public float readFloat() throws IOException
readFloat
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public double readDouble() throws IOException
readDouble
在界面
DataInput
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public void readFully(byte[] buf) throws IOException
readFully
在界面
DataInput
buf
- 读取数据的缓冲区
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public void readFully(byte[] buf, int off, int len) throws IOException
readFully
在界面
DataInput
buf
- 读取数据的缓冲区
off
- 数据的起始偏移量
len
- 要读取的最大字节数
EOFException
- 如果达到文件结尾。
IOException
- 如果发生其他I / O错误。
public int skipBytes(int len) throws IOException
skipBytes
在界面
DataInput
len
- 要跳过的字节数
IOException
- 如果发生I / O错误。
@Deprecated public String readLine() throws IOException
readLine
在界面
DataInput
IOException
- 从底层
InputStream
读取时是否存在I / O错误
public String readUTF() throws IOException
readUTF
在界面
DataInput
IOException
- 从底层
InputStream
读取时是否存在I / O错误
UTFDataFormatException
- 如果读取的字节不表示字符串的有效修改的UTF-8编码