java.lang.Object java.io.OutputStream java.io.ObjectOutputStream
public class ObjectOutputStream
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 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 接口的任何对象的字段。不可序列化的 Object 的子类可以是可序列化的。在此情况下,不可序列化的类必须有一个无参数构造方法,以便允许初始化其字段。在此情况下,子类负责保存和恢复不可序列化的类的状态。经常出现的情况是,该类的字段是可访问的(public、package 或 protected),或者存在可用来恢复状态的 get 和 set 方法。
在 writeObject 和 readObject 方法的实现中抛出 NotSerializableException,可以阻止对象的序列化。ObjectOutputStream 将捕获异常并中止序列化进程。
实现 Externalizable 接口允许对象假定可以完全控制对象的序列化形式的内容和格式。调用 Externalizable 接口的方法(writeExternal 和 readExternal)来保存和恢复对象的状态。通过类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法读写它们自己的状态。对象负责处理出现的任何版本控制。
Enum 常量的序列化不同于普通的 serializable 或 externalizable 对象。enum 常量的序列化形式只包含其名称;常量的字段值不被传送。为了序列化 enum 常量,ObjectOutputStream 需要写入由常量的名称方法返回的字符串。与其他 serializable 或 externalizable 对象一样,enum 常量可以作为序列化流中后续出现的 back 引用的目标。用于序列化 enum 常量的进程不可定制;在序列化期间,由 enum 类型定义的所有类特定的 writeObject 和 writeReplace 方法都将被忽略。类似地,任何 serialPersistentFields 或 serialVersionUID 字段声明也将被忽略,所有 enum 类型都有一个 0L 的固定的 serialVersionUID。
基本数据(不包括 serializable 字段和 externalizable 数据)以块数据记录的形式写入 ObjectOutputStream 中。块数据记录由头部和数据组成。块数据部分包括标记和跟在部分后面的字节数。连续的基本写入数据被合并在一个块数据记录中。块数据记录的分块因子为 1024 字节。每个块数据记录都将填满 1024 字节,或者在终止块数据模式时被写入。调用 ObjectOutputStream 方法 writeObject、defaultWriteObject 和 writeFields 最初只是终止所有现有块数据记录。
DataOutput
,
ObjectInputStream
,
Serializable
,
Externalizable
,
Serialization Specification, Section 2, Object Output Classes
嵌套类摘要 | |
---|---|
static class |
ObjectOutputStream.PutField 提供对要写入 ObjectOutput 的持久字段的编程访问。 |
字段摘要 |
---|
构造方法摘要 | |
---|---|
protected |
ObjectOutputStream() 为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。 |
|
ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream。 |
方法摘要 | |
---|---|
protected void |
annotateClass(Class<?> cl) 子类可以实现此方法,从而允许在流中存储类数据。 |
protected void |
annotateProxyClass(Class<?> cl) 子类可以实现此方法,从而在流中存储定制数据和动态代理类的描述符。 |
void |
close() 关闭流。 |
void |
defaultWriteObject() 将当前类的非静态和非瞬态字段写入此流。 |
protected void |
drain() 排空 ObjectOutputStream 中的所有已缓冲数据。 |
protected boolean |
enableReplaceObject(boolean enable) 允许流对流中的对象进行替换。 |
void |
flush() 刷新该流的缓冲。 |
ObjectOutputStream.PutField |
putFields() 获取用于缓冲写入流中的持久存储字段的对象。 |
protected Object |
replaceObject(Object obj) 在序列化期间,此方法允许 ObjectOutputStream 的受信任子类使用一个对象替代另一个对象。 |
void |
reset() 重置将丢弃已写入流中的所有对象的状态。 |
void |
useProtocolVersion(int version) 指定要在写入流时使用的流协议版本。 |
void |
write(byte[] buf) 写入一个 byte 数组。 |
void |
write(byte[] buf, int off, int len) 写入字节的子数组。 |
void |
write(int val) 写入一个字节。 |
void |
writeBoolean(boolean val) 写入一个 boolean 值。 |
void |
writeByte(int val) 写入一个 8 位字节。 |
void |
writeBytes(String str) 以字节序列形式写入一个 String。 |
void |
writeChar(int val) 写入一个 16 位的 char 值。 |
void |
writeChars(String str) 以 char 序列形式写入一个 String。 |
protected void |
writeClassDescriptor(ObjectStreamClass desc) 将指定的类描述符写入 ObjectOutputStream。 |
void |
writeDouble(double val) 写入一个 64 位的 double 值。 |
void |
writeFields() 将已缓冲的字段写入流中。 |
void |
writeFloat(float val) 写入一个 32 位的 float 值。 |
void |
writeInt(int val) 写入一个 32 位的 int 值。 |
void |
writeLong(long val) 写入一个 64 位的 long 值。 |
void |
writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。 |
protected void |
writeObjectOverride(Object obj) 子类用于重写默认 writeObject 方法的方法。 |
void |
writeShort(int val) 写入一个 16 位的 short 值。 |
protected void |
writeStreamHeader() 提供 writeStreamHeader 方法,这样子类可以将其自身的头部添加或预加到流中。 |
void |
writeUnshared(Object obj) 将“未共享”对象写入 ObjectOutputStream。 |
void |
writeUTF(String str) 以 UTF-8 修改版格式写入此 String 的基本数据。 |
从类 java.lang.Object 继承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
构造方法详细信息 |
---|
public ObjectOutputStream(OutputStream out) throws IOException
如果安装了安全管理器,则在通过重写 ObjectOutputStream.putFields 或 ObjectOutputStream.writeUnshared 方法的子类的构造方法来直接或间接调用此构造方法时,它将对 "enableSubclassImplementation" SerializablePermission 进行检查。
out
- 要写入数据的输出流
IOException
- 如果在写入流部分时发生 I/O 错误
SecurityException
- 如果不受信任的子类非法重写安全敏感方法
NullPointerException
- 如果
out
为
null
ObjectOutputStream()
,
putFields()
,
ObjectInputStream.ObjectInputStream(InputStream)
protected ObjectOutputStream() throws IOException, SecurityException
如果已经安装了安全管理器,则此方法首先利用 SerializablePermission("enableSubclassImplementation")
权限调用安全管理器的 checkPermission
方法,以确保可以启用子类化。
SecurityException
- 如果安全管理器存在,且其
checkPermission
方法不允许启用子类化。
IOException
SecurityManager.checkPermission(java.security.Permission)
,
SerializablePermission
方法详细信息 |
---|
public void useProtocolVersion(int version) throws IOException
此例程提供了一个钩子 (hook),允许以与旧版的流格式向后兼容的格式写入当前版的 Serialization。
我们将尽最大努力避免造成额外的向后不兼容性;但有时没有其他替代方法。
version
- 根据 java.io.ObjectStreamConstants 使用 ProtocolVersion。
IllegalStateException
- 如果在已序列化所有对象后调用。
IllegalArgumentException
- 如果传入的版本无效。
IOException
- 如果发生 I/O 错误
ObjectStreamConstants.PROTOCOL_VERSION_1
,
ObjectStreamConstants.PROTOCOL_VERSION_2
public final void writeObject(Object obj) throws IOException
当 OutputStream 中出现问题或者遇到不应序列化的类时,将抛出异常。所有异常对于 OutputStream 而言都是致命的,使其处于不确定状态;并由调用者来忽略或恢复流的状态。
ObjectOutput
中的
writeObject
obj
- 要写入的对象
InvalidClassException
- 序列化操作使用的类出了问题。
NotSerializableException
- 某个要序列化的对象不能实现 java.io.Serializable 接口。
IOException
- 由底层 OutputStream 抛出的任何异常。
protected void writeObjectOverride(Object obj) throws IOException
obj
- 要写入底层流的对象
IOException
- 如果写入底层流时发生 I/O 错误
ObjectOutputStream()
,
writeObject(Object)
public void writeUnshared(Object obj) throws IOException
重写此方法的 ObjectOutputStream 子类只能在处理 "enableSubclassImplementation" SerializablePermission 的安全上下文中构造;在不具有此权限的情况下,任何实例化这种子类的尝试都将导致抛出 SecurityException。
obj
- 要写入流的对象
NotSerializableException
- 如果要序列化的图形中的对象不能实现 Serializable 接口
InvalidClassException
- 如果要序列化的对象的类存在问题
IOException
- 如果序列化期间发生 I/O 错误
public void defaultWriteObject() throws IOException
IOException
- 如果在写入底层
OutputStream
中时发生 I/O 错误
public ObjectOutputStream.PutField putFields() throws IOException
IOException
- 如果发生 I/O 错误
public void writeFields() throws IOException
IOException
- 如果在写入底层流时发生 I/O 错误
NotActiveException
- 未调用类 writeObject 方法来写入对象的状态时调用。
public void reset() throws IOException
IOException
- 如果在序列化对象时调用 reset()。
protected void annotateClass(Class<?> cl) throws IOException
cl
- 注释定制数据的类
IOException
- 底层 OutputStream 抛出任何异常。
protected void annotateProxyClass(Class<?> cl) throws IOException
对于流中的每个唯一的代理类描述符,此方法只调用一次。在 ObjectOutputStream
中,此方法的默认实现不执行任何操作。
ObjectInputStream
中的相应方法是 resolveProxyClass
。对于重写此方法的 ObjectOutputStream
的给定子类,ObjectInputStream
的相应子类中的 resolveProxyClass
方法必须读取由 annotateProxyClass
写入的所有数据或对象。
cl
- 注释定制数据的代理类
IOException
- 底层
OutputStream
抛出的任何异常
ObjectInputStream.resolveProxyClass(String[])
protected Object replaceObject(Object obj) throws IOException
ObjectOutputStream.writeObject 方法使用 Object 类型的参数(相对于 Serializable 类型),允许非 serializable 对象由 serializable 对象取代。
在子类取代对象时,必须确保要么在反序列化期间进行互补替代,要么替代对象与存储引用的每个字段兼容。如果对象的类型不是字段或数组元素类型的子类,则通过引发异常中止序列化并且不存储对象。
此方法仅在首次遇到每个对象时调用一次。对象的所有后续引用都将被重定向到新对象。此方法应该返回要替代的对象或初始对象。
替代对象时可以返回 null,但是在包含到初始对象的引用的类中可能导致 NullReferenceException,因为它们可能期望得到对象而不是 null。
obj
- 要取代的对象
IOException
- 底层 OutputStream 抛出的任何异常。
protected boolean enableReplaceObject(boolean enable) throws SecurityException
如果 enable
为 true,并且安装了安全管理器,则此方法首先利用 SerializablePermission("enableSubstitution")
权限调用安全管理器的 checkPermission
方法,以确保允许流对流中的对象进行替换。
enable
- 允许取代对象的 boolean 参数
SecurityException
- 如果安全管理器存在,且其
checkPermission
方法不允许流对流中的对象进行替换。
SecurityManager.checkPermission(java.security.Permission)
,
SerializablePermission
protected void writeStreamHeader() throws IOException
IOException
- 如果在写入底层流时发生 I/O 错误
protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException
readClassDescriptor
),以便根据其定制的流表示形式来重构类描述符。默认情况下,此方法根据 Object Serialization 规范中定义的格式写入类描述符。
注意,仅当 ObjectOutputStream 没有使用旧的序列化流格式(通过调用 ObjectOutputStream 的 useProtocolVersion
方法设置)时才调用此方法。如果此序列化流在使用旧的格式(即 PROTOCOL_VERSION_1
),则以不可重写或自定义的方式在内部写入类描述符。
desc
- 要写入流的类描述符
IOException
- 如果发生 I/O 错误。
ObjectInputStream.readClassDescriptor()
,
useProtocolVersion(int)
,
ObjectStreamConstants.PROTOCOL_VERSION_1
public void write(int val) throws IOException
DataOutput
中的
write
ObjectOutput
中的
write
OutputStream
中的
write
val
- 要写入流中的字节
IOException
- 如果发生 I/O 错误。
public void write(byte[] buf) throws IOException
DataOutput
中的
write
ObjectOutput
中的
write
OutputStream
中的
write
buf
- 要写入的数据
IOException
- 如果发生 I/O 错误。
OutputStream.write(byte[], int, int)
public void write(byte[] buf, int off, int len) throws IOException
DataOutput
中的
write
ObjectOutput
中的
write
OutputStream
中的
write
buf
- 要写入的数据
off
- 数据中的初始偏移量
len
- 写入的字节数
IOException
- 如果发生 I/O 错误。
public void flush() throws IOException
Flushable
中的
flush
ObjectOutput
中的
flush
OutputStream
中的
flush
IOException
- 如果发生 I/O 错误。
protected void drain() throws IOException
IOException
- 如果在将数据写入底层流时发生 I/O 错误
public void close() throws IOException
Closeable
中的
close
ObjectOutput
中的
close
OutputStream
中的
close
IOException
- 如果发生 I/O 错误。
public void writeBoolean(boolean val) throws IOException
DataOutput
中的
writeBoolean
val
- 要写入的 boolean 值
IOException
- 如果在将数据写入底层流时发生 I/O 错误
public void writeByte(int val) throws IOException
DataOutput
中的
writeByte
val
- 要写入的字节值
IOException
- 如果在将数据写入底层流时发生 I/O 错误