java.io

接口
异常
错误
java.lang.Object
  继承者 java.io.OutputStream
      继承者 java.io.ObjectOutputStream
所有已实现的接口:
Closeable, DataOutput, Flushable, ObjectOutput, ObjectStreamConstants

public class ObjectOutputStream
     
extends OutputStream
implements ObjectOutput, ObjectStreamConstants

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 最初只是终止所有现有块数据记录。

从以下版本开始:
JDK1.1
另请参见:
DataOutput, ObjectInputStream, Serializable, Externalizable, Serialization Specification, Section 2, Object Output Classes

嵌套类摘要
static class ObjectOutputStream.PutField
          提供对要写入 ObjectOutput 的持久字段的编程访问。
 
字段摘要
 
从接口 java.io.ObjectStreamConstants 继承的字段
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
 
构造方法摘要
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
 

构造方法详细信息

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.ObjectInputStream(InputStream)

ObjectOutputStream

protected ObjectOutputStream()
                      throws IOException,
                             SecurityException
为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。

如果已经安装了安全管理器,则此方法首先利用 SerializablePermission("enableSubclassImplementation") 权限调用安全管理器的 checkPermission 方法,以确保可以启用子类化。

抛出:
SecurityException - 如果安全管理器存在,且其 checkPermission 方法不允许启用子类化。
IOException
另请参见:
SecurityManager.checkPermission(java.security.Permission), SerializablePermission
方法详细信息

useProtocolVersion

public void useProtocolVersion(int version)
                        throws IOException
指定要在写入流时使用的流协议版本。

此例程提供了一个钩子 (hook),允许以与旧版的流格式向后兼容的格式写入当前版的 Serialization。

我们将尽最大努力避免造成额外的向后不兼容性;但有时没有其他替代方法。

参数:
version - 根据 java.io.ObjectStreamConstants 使用 ProtocolVersion。
抛出:
IllegalStateException - 如果在已序列化所有对象后调用。
IllegalArgumentException - 如果传入的版本无效。
IOException - 如果发生 I/O 错误
从以下版本开始:
1.2
另请参见:
ObjectStreamConstants.PROTOCOL_VERSION_1, ObjectStreamConstants.PROTOCOL_VERSION_2

writeObject

public final void writeObject(Object obj)
                       throws IOException
将指定的对象写入 ObjectOutputStream。对象的类、类的签名,以及类及其所有超类型的非瞬态和非静态字段的值都将被写入。可以使用 writeObject 和 readObject 方法重写类的默认序列化。由此对象引用的对象是以可变迁的方式写入的,这样,可以通过 ObjectInputStream 重新构造这些对象的完全等价的图形。

当 OutputStream 中出现问题或者遇到不应序列化的类时,将抛出异常。所有异常对于 OutputStream 而言都是致命的,使其处于不确定状态;并由调用者来忽略或恢复流的状态。

指定者:
接口 ObjectOutput 中的 writeObject
参数:
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,不同点在于它总是将给定对象作为流中唯一的新对象进行写入(相对于指向以前序列化实例的 back 引用而言)。尤其是:
  • 通过 writeUnshared 写入的对象总是作为新出现对象(未曾将对象写入流中)被序列化,不管该对象以前是否已经被写入过。
  • 如果使用 writeObject 写入以前通过 writeUnshared 写入的对象,则可将以前的 writeUnshared 操作视为写入一个单独对象。换句话说,ObjectOutputStream 永远不会生成通过调用 writeUnshared 写入的对象数据的 back 引用。
虽然通过 writeUnshared 写入对象本身不能保证反序列化对象时对象引用的唯一性,但它允许在流中多次定义单个对象,因此接收方对 readUnshared 的多个调用不会引发冲突。注意,上述规则仅应用于通过 writeUnshared 写入的基层对象,而不能应用于要序列化的对象图形中的任何可变迁方式引用的子对象。

重写此方法的 ObjectOutputStream 子类只能在处理 "enableSubclassImplementation" SerializablePermission 的安全上下文中构造;在不具有此权限的情况下,任何实例化这种子类的尝试都将导致抛出 SecurityException。

参数:
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 方法时,字段被写入流中。

返回:
保存 serializable 字段的 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 相同。将流中的当前点标记为 reset,相应的 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。对于重写此方法的 ObjectOutputStream 的给定子类,ObjectInputStream 的相应子类中的 resolveProxyClass 方法必须读取由 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 类型),允许非 serializable 对象由 serializable 对象取代。

在子类取代对象时,必须确保要么在反序列化期间进行互补替代,要么替代对象与存储引用的每个字段兼容。如果对象的类型不是字段或数组元素类型的子类,则通过引发异常中止序列化并且不存储对象。

此方法仅在首次遇到每个对象时调用一次。对象的所有后续引用都将被重定向到新对象。此方法应该返回要替代的对象或初始对象。

替代对象时可以返回 null,但是在包含到初始对象的引用的类中可能导致 NullReferenceException,因为它们可能期望得到对象而不是 null。

参数:
obj - 要取代的对象
返回:
取代指定对象的替换对象
抛出:
IOException - 底层 OutputStream 抛出的任何异常。

enableReplaceObject

protected boolean enableReplaceObject(boolean enable)
                               throws SecurityException
允许流对流中的对象进行替换。启用时,将为正序列化的每个对象调用 replaceObject 方法。

如果 enable 为 true,并且安装了安全管理器,则此方法首先利用 SerializablePermission("enableSubstitution") 权限调用安全管理器的 checkPermission 方法,以确保允许流对流中的对象进行替换。

参数:
enable - 允许取代对象的 boolean 参数
返回:
调用此方法之前的以前的设置
抛出:
SecurityException - 如果安全管理器存在,且其 checkPermission 方法不允许流对流中的对象进行替换。
另请参见:
SecurityManager.checkPermission(java.security.Permission), SerializablePermission

writeStreamHeader

protected void writeStreamHeader()
                          throws IOException
提供 writeStreamHeader 方法,这样子类可以将其自身的头部添加或预加到流中。它可以将幻数 (magic number) 和版本写入流。

抛出:
IOException - 如果在写入底层流时发生 I/O 错误

writeClassDescriptor

protected void writeClassDescriptor(ObjectStreamClass desc)
                             throws IOException
将指定的类描述符写入 ObjectOutputStream。类描述符用于标识写入流中的对象的类。ObjectOutputStream 的子类可以重写此方法,从而定制将类描述符写入序列化流中的方式。然后,应该重写 ObjectInputStream 中的相应方法( readClassDescriptor),以便根据其定制的流表示形式来重构类描述符。默认情况下,此方法根据 Object Serialization 规范中定义的格式写入类描述符。

注意,仅当 ObjectOutputStream 没有使用旧的序列化流格式(通过调用 ObjectOutputStream 的 useProtocolVersion 方法设置)时才调用此方法。如果此序列化流在使用旧的格式(即 PROTOCOL_VERSION_1),则以不可重写或自定义的方式在内部写入类描述符。

参数:
desc - 要写入流的类描述符
抛出:
IOException - 如果发生 I/O 错误。
从以下版本开始:
1.3
另请参见:
ObjectInputStream.readClassDescriptor(), useProtocolVersion(int), ObjectStreamConstants.PROTOCOL_VERSION_1

write

public void write(int val)
           throws IOException
写入一个字节。在实际写入字节前,此方法将发生阻塞。

指定者:
接口 DataOutput 中的 write
指定者:
接口 ObjectOutput 中的 write
指定者:
OutputStream 中的 write
参数:
val - 要写入流中的字节
抛出:
IOException - 如果发生 I/O 错误。

write

public void write(byte[] buf)
           throws IOException
写入一个 byte 数组。在实际写入字节前,此方法将发生阻塞。

指定者:
接口 DataOutput 中的 write
指定者:
接口 ObjectOutput 中的 write
覆盖:
OutputStream 中的 write
参数:
buf - 要写入的数据
抛出:
IOException - 如果发生 I/O 错误。
另请参见:
OutputStream.write(byte[], int, int)

write

public void write(byte[] buf,
                  int off,
                  int len)
           throws IOException
写入字节的子数组。

指定者:
接口 DataOutput 中的 write
指定者:
接口 ObjectOutput 中的 write
覆盖:
OutputStream 中的 write
参数:
buf - 要写入的数据
off - 数据中的初始偏移量
len - 写入的字节数
抛出:
IOException - 如果发生 I/O 错误。

flush

public void flush()
           throws IOException
刷新该流的缓冲。此操作将写入所有已缓冲的输出字节,并将它们刷新到底层流中。

指定者:
接口 Flushable 中的 flush
指定者:
接口 ObjectOutput 中的 flush
覆盖:
OutputStream 中的 flush
抛出:
IOException - 如果发生 I/O 错误。

drain

protected void drain()
              throws IOException
排空 ObjectOutputStream 中的所有已缓冲数据。与刷新类似,但没有将刷新传播到底层流。

抛出:
IOException - 如果在将数据写入底层流时发生 I/O 错误

close

public void close()
           throws IOException
关闭流。必须调用此方法来释放与此流有关的所有资源。

指定者:
接口 Closeable 中的 close
指定者:
接口 ObjectOutput 中的 close
覆盖:
OutputStream 中的 close
抛出:
IOException - 如果发生 I/O 错误。

writeBoolean

public void writeBoolean(boolean val)
                  throws IOException
写入一个 boolean 值。

指定者:
接口 DataOutput 中的 writeBoolean
参数:
val - 要写入的 boolean 值
抛出:
IOException - 如果在将数据写入底层流时发生 I/O 错误

writeByte

public void writeByte(int val)
               throws IOException
写入一个 8 位字节。

指定者:
接口 DataOutput 中的 writeByte
参数:
val - 要写入的字节值
抛出:
IOException - 如果在将数据写入底层流时发生 I/O 错误