|
|||||||||
摘要: 嵌套 | 字段 | 构造方法 | 方法 | 详细信息: 字段 | 构造方法 | 方法 |
java.io
类 ObjectInputStream
java.lang.Object java.io.InputStream java.io.ObjectInputStream
- 所有已实现的接口:
- Closeable, DataInput, ObjectInput, ObjectStreamConstants
-
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 接口允许对象序列化,以保存和还原对象的全部状态,并且允许类在写入流时的状态和从流读取时的状态之间变化。它自动遍历对象之间的引用,保存和还原全部图形。
在序列化和反序列化进程中需要特殊处理的 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 方法写入的超出自定义数据边界的对象数据将导致抛出 OptionalDataException(eof 字段值为 true)。超出已分配数据末尾的非对象读取以指示流末尾的方式反映数据末尾:按位读取与字节读取或字节数读取一样,将返回 -1,基元读取将抛出 EOFException。如果不存在对应的 writeObject 方法,则默认的序列化数据的末尾标记已分配数据的末尾。
从 readExternal 方法发出的基元和对象读取调用的行为方式一样:如果流已经定位在由相应 writeExternal 方法写入的数据末尾,则对象读取将抛出 OptionalDataException(其 eof 设置为 true),按位读取将返回 -1,基元读取将抛出 EOFException。注意,此行为不适用于使用旧 ObjectStreamConstants.PROTOCOL_VERSION_1
协议写入的流,在这些流中,没有划分出由 writeExternal 方法写入的数据末尾,因此无法检测。
如果序列化流没有将给定类列为要反序列化的对象的超类,则 readObjectNoData 方法负责初始化其特定类的对象状态。在接收方使用的反序列化实例类的版本不同于发送方,并且接收者版本扩展的类不是发送者版本扩展的类时,此事可能发生。如果序列化流已经被篡改,也会发生这种情况;因此,不管源流是“敌意的”还是不完整的,readObjectNoData 方法都可以用来正确地初始化反序列化的对象。
对于没有实现 java.io.Serializable 接口的任何对象,序列化不会对其字段进行读取或赋值。非 serializable 的 Object 的子类可以为 serializable。在此情况下,非 serializable 类必须具有无参数的构造方法以允许其字段能被初始化。在此情况下,子类负责保存和还原非 serializable 类的状态。经常出现的情况是,该类的字段是可访问的(public、package 或 protected),或者存在可用于还原状态的 get 和 set 方法。
反序列化对象进程中发生的所有异常将由 ObjectInputStream 捕获并将中止读取进程。
实现 Externalizable 接口允许对象假定可以完全控制对象的序列化形式的内容和格式。调用 Externalizable 接口的方法(writeExternal 和 readExternal)来保存和恢复对象状态。当这两种方法被某个类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法读写其本身的状态。对象负责处理出现的任何版本控制。
Enum 常量的反序列化不同于普通的 serializable 或 externalizable 对象。Enum 常量的序列化形式只包含其名称;不传送常量的字段值。要反序列化 enum 常量,ObjectInputStream 需要从流中读取常量的名称;然后将 enum 常量的基本类型和接收到的常量名称作为参数,调用静态方法 Enum.valueOf(Class, String)
获取反序列化的常量。与其他 serializable 或 externalizable 对象一样,enum 常量可以作为序列化流中随后出现的反向引用的目标。不可以自定义 enum 常量的反序列化进程:在反序列化期间,enum 类型所定义的任何与类有关的 readObject、readObjectNoData 和 readResolve 方法都将被忽略。类似地,任何 serialPersistentFields 或 serialVersionUID 字段声明也将被忽略(所有 enum 类型都有一个固定的 0L 的 serialVersionUID)。
- 从以下版本开始:
- JDK1.1
- 另请参见:
-
DataInput
,ObjectOutputStream
,Serializable
, Object Serialization Specification, Section 3, Object Input Classes
嵌套类摘要 | |
---|---|
static class |
ObjectInputStream.GetField 提供对从输入流读取的持久字段的访问权限。 |
字段摘要 |
---|
构造方法摘要 | |
---|---|
protected |
ObjectInputStream() 为完全重新实现 ObjectInputStream 的子类提供一种方式,让它不必分配仅由 ObjectInputStream 的实现使用的私有数据。 |
|
ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream。 |
方法摘要 | |
---|---|
int |
available() 返回可以不受阻塞地读取的字节数。 |
void |
close() 关闭输入流。 |
void |
defaultReadObject() 从此流读取当前类的非静态和非瞬态字段。 |
protected boolean |
enableResolveObject(boolean enable) 启用允许从要替代的流读取对象的流。 |
int |
read() 读取数据字节。 |
int |
read(byte[] buf, int off, int len) 读入字节数组。 |
boolean |
readBoolean() 以 boolean 形式读取。 |
byte |
readByte() 读取一个 8 位的字节。 |
char |
readChar() 读取一个 16 位的 char 值。 |
protected ObjectStreamClass |
readClassDescriptor() 从序列化流读取类描述符。 |
double |
readDouble() 读取一个 64 位的 double 值。 |
ObjectInputStream.GetField |
readFields() 按名称从流中读取持久字段并使其可用。 |
float |
readFloat() 读取一个 32 位的 float 值。 |
void |
readFully(byte[] buf) 读取字节,在读取所有字节前将发生阻塞。 |
void |
readFully(byte[] buf, int off, int len) 读取字节,在读取所有字节之前将发生阻塞。 |
int |
readInt() 读取一个 32 位的 int 值。 |
String |
readLine() 已过时。 此方法不能正确地将字节转换为字符。请参见 DataInputStream 以获取详细信息和替代方法。 |
long |
readLong() 读取一个 64 位的 long 值。 |
Object |
readObject() 从 ObjectInputStream 读取对象。 |
protected Object |
readObjectOverride() 此方法由使用受保护的无参数构造方法构造 ObjectOutputStream 的 ObjectOutputStream 的受信任子类调用。 |
short |
readShort() 读取一个 16 位的 short 值。 |
protected void |
readStreamHeader() 提供的 readStreamHeader 方法允许子类读取并验证它们自己的流头部。 |
Object |
readUnshared() 从 ObjectInputStream 读取“非共享”对象。 |
int |
readUnsignedByte() 读取一个无符号的 8 位字节。 |
int |
readUnsignedShort() 读取一个无符号的 16 位 short 值。 |
String |
readUTF() 读取 UTF-8 修改版格式的 String。 |
void |
registerValidation(ObjectInputValidation obj, int prio) 在返回图形前注册要验证的对象。 |
protected Class<?> |
resolveClass(ObjectStreamClass desc) 加载指定流类描述的本地等价类。 |
protected Object |
resolveObject(Object obj) 在反序列化期间,此方法允许 ObjectInputStream 的受信任子类使用一个对象替代另一个。 |
protected Class<?> |
resolveProxyClass(String[] interfaces) 返回一个代理类,该类实现在代理类描述符中命名的接口;子类可以实现此方法,以便从流及动态代理类的描述符中读取自定义数据,允许它们使用接口和代理类的替换加载机制。 |
int |
skipBytes(int len) 跳过字节,在跳过所有字节之前将发生阻塞。 |
从类 java.io.InputStream 继承的方法 |
---|
mark, markSupported, read, reset, skip |
从类 java.lang.Object 继承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
从接口 java.io.ObjectInput 继承的方法 |
---|
read, skip |
构造方法详细信息 |
---|
ObjectInputStream
public ObjectInputStream(InputStream in) throws IOException
-
创建从指定 InputStream 读取的 ObjectInputStream。从流读取序列化头部并予以验证。在对应的 ObjectOutputStream 写入并刷新头部之前,此构造方法将阻塞。
如果安装了安全管理器,则重写 ObjectInputStream.readFields 或 ObjectInputStream.readUnshared 方法的子类的构造方法直接或间接调用此构造方法时,它将对 "enableSubclassImplementation" SerializablePermission 进行检查。
- 参数:
-
in
- 要从中读取的输入流 - 抛出:
-
StreamCorruptedException
- 如果流的头部不正确 -
IOException
- 如果读取流头部时发生 I/O 错误 -
SecurityException
- 如果不受信任的子类非法重写安全敏感的方法 -
NullPointerException
- 如果in
为null
- 另请参见:
-
ObjectInputStream()
,readFields()
,ObjectOutputStream.ObjectOutputStream(OutputStream)
ObjectInputStream
protected ObjectInputStream() throws IOException, SecurityException
-
为完全重新实现 ObjectInputStream 的子类提供一种方式,让它不必分配仅由 ObjectInputStream 的实现使用的私有数据。
如果已经安装了安全管理器,则此方法首先通过
SerializablePermission("enableSubclassImplementation")
权限调用安全管理器的checkPermission
方法,以确保可以启用子类化。- 抛出:
-
SecurityException
- 如果安全管理器存在并且其checkPermission
方法不允许启用子类化。 -
IOException
- 另请参见:
-
SecurityManager.checkPermission(java.security.Permission)
,SerializablePermission
方法详细信息 |
---|
readObject
public final Object readObject() throws IOException, ClassNotFoundException
-
从 ObjectInputStream 读取对象。对象的类、类的签名和类及所有其超类型的非瞬态和非静态字段的值都将被读取。可以使用 writeObject 和 readObject 方法为类重写默认的反序列化。由此对象引用的对象是可传递读取的,这样 readObject 即可重新构造这些对象的完全等价的图形。
通过完全还原根对象的所有字段及其引用的对象来完全还原根对象。此时,对象验证回调的执行顺序基于其注册优先级。回调在其个别还原时由对象(按照 readObject 特定方法)进行注册。
当 InputStream 中出现问题或者遇到不应反序列化的类时,将抛出异常。所有异常对于 InputStream 而言都是致命的,将使其处于不确定状态;这将持续到调用方忽略或恢复流状态。
-
- 指定者:
-
接口
ObjectInput
中的readObject
-
- 返回:
- 从流读取的对象
- 抛出:
-
ClassNotFoundException
- 找不到序列化对象的类。 -
InvalidClassException
- 序列化使用的类出了问题。 -
StreamCorruptedException
- 流中的控制信息不一致。 -
OptionalDataException
- 在流中而不是对象中找到了基本数据。 -
IOException
- 任何常规的输入/输出相关的异常。
readObjectOverride
protected Object readObjectOverride() throws IOException, ClassNotFoundException
- 此方法由使用受保护的无参数构造方法构造 ObjectOutputStream 的 ObjectOutputStream 的受信任子类调用。子类需要使用修改符 "final" 提供重写方法。
-
-
- 返回:
- 从流读取的 Object。
- 抛出:
-
ClassNotFoundException
- 找不到序列化对象的类定义。 -
OptionalDataException
- 在流中而不是对象中找到了基本数据。 -
IOException
- 如果从基础流执行读操作时发生 I/O 错误 - 从以下版本开始:
- 1.2
- 另请参见:
-
ObjectInputStream()
,readObject()
readUnshared
public Object readUnshared() throws IOException, ClassNotFoundException
-
从 ObjectInputStream 读取“非共享”对象。此方法与 readObject 类似,不同点在于它可以防止对 readObject 和 readUnshared 的后续调用返回对通过此调用获取的反序列化实例的附加引用。尤其是:
- 如果调用 readUnshared 反序列化 back 引用(以前写入流的对象的流表示形式),则抛出 ObjectStreamException。
- 如果 readUnshared 成功返回,则反序列化对由 readUnshared 反序列化的流句柄的 back 引用的任何后续尝试,都将导致抛出 ObjectStreamException。
但是,对于不是 enum 常量或 java.lang.Class 实例且没有定义 readResolve 方法的对象,readUnshared 保证返回的对象引用是惟一的,不可从创建它的 ObjectInputStream 中再一次获取,即使操作基础数据流也是如此。此规则保证仅应用于由 readUnshared 返回的基层对象,而不能应用于返回对象图形中的任何以传递方式引用的子对象。
重写此方法的 ObjectInputStream 子类只能在处理 "enableSubclassImplementation" SerializablePermission 的安全上下文中构造;在不具有此权限的情况下,任何实例化这种子类的尝试都将导致抛出 SecurityException。
-
-
- 返回:
- 反序列化对象的引用
- 抛出:
-
ClassNotFoundException
- 如果找不到要反序列化的对象的类 -
StreamCorruptedException
- 如果流中的控制信息不一致 -
ObjectStreamException
- 如果流中已经出现了要反序列化的对象 -
OptionalDataException
- 如果基本数据是流中的下一项 -
IOException
- 如果在反序列化期间发生 I/O 错误
defaultReadObject
public void defaultReadObject() throws IOException, ClassNotFoundException
- 从此流读取当前类的非静态和非瞬态字段。此方法只能从正在反序列化的类的 readObject 方法中调用。如果从其他地方调用该字段,则将抛出 NotActiveException。
-
-
- 抛出:
-
ClassNotFoundException
- 如果找不到序列化对象的类。 -
IOException
- 如果发生 I/O 错误。 -
NotActiveException
- 如果目前流没有正在读取对象。
readFields
public ObjectInputStream.GetField readFields() throws IOException, ClassNotFoundException
- 按名称从流中读取持久字段并使其可用。
-
-
- 返回:
-
表示正在反序列化的对象持久字段的
GetField
对象 - 抛出:
-
ClassNotFoundException
- 如果找不到序列化对象的类。 -
IOException
- 如果发生 I/O 错误。 -
NotActiveException
- 如果目前流没有正在读取对象。 - 从以下版本开始:
- 1.2
registerValidation
public void registerValidation(ObjectInputValidation obj, int prio) throws NotActiveException, InvalidObjectException
- 在返回图形前注册要验证的对象。与 resolveObject 类似,这些验证是在重构整个图形后调用的。通常,readObject 方法向流注册对象,这样还原全部对象后,就可以执行最后一组验证了。
-
-
- 参数:
-
obj
- 接收验证回调的对象。 -
prio
- 控制回调的顺序;零是个好的默认值。使用较大数进行较高的回调,使用较小数进行较晚的回调。在一个优先级中,回调的处理没有特定顺序。 - 抛出:
-
NotActiveException
- 因为目前流没有正在读取对象,所以注册回调无效。 -
InvalidObjectException
- 验证对象为 null。