- 所有已实现的接口:
Closeable,DataOutput,Flushable,ObjectOutput,ObjectStreamConstants,AutoCloseable
只有支持 java.io.Serializable 接口的对象才能写入流。每个可序列化对象的类都经过编码,包括类名和类签名、对象字段和数组的值,以及从初始对象引用的任何其他对象的闭包。
writeObject 方法用于将对象写入流。任何对象,包括字符串和数组,都是用 writeObject 编写的。可以将多个对象或基元写入流。对象必须从相应的 ObjectInputstream 中以相同的类型和相同的写入顺序读回。
还可以使用 DataOutput 中的适当方法将原始数据类型写入流。也可以使用 writeUTF 方法写入字符串。
对象的默认序列化机制写入对象的类、类签名以及所有非瞬态和非静态字段的值。对其他对象的引用(瞬态或静态字段除外)会导致这些对象也被写入。对单个对象的多个引用使用引用共享机制进行编码,以便对象图可以恢复到与原始写入时相同的形状。
例如,编写一个可以被 ObjectInputStream 中的示例读取的对象:
try (FileOutputStream fos = new FileOutputStream("t.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject("Today");
oos.writeObject(LocalDateTime.now());
} catch (Exception ex) {
// handle exception
}
在序列化和反序列化过程中需要特殊处理的可序列化类应该实现具有以下签名的方法:
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 接口的对象的字段。不可序列化的对象的子类可以是可序列化的。在这种情况下,不可序列化的类必须有一个无参数的构造方法来允许初始化它的字段。在这种情况下,子类有责任保存和恢复不可序列化类的状态。通常情况下,该类的字段是可访问的(public、package 或 protected),或者存在可用于恢复状态的 get 和 set 方法。
可以通过实现抛出 NotSerializableException 的 writeObject 和 readObject 方法来防止对象的序列化。异常将被 ObjectOutputStream 捕获并中止序列化过程。
实现 Externalizable 接口允许对象完全控制对象序列化形式的内容和格式。调用 Externalizable 接口的方法 writeExternal 和 readExternal 来保存和恢复对象状态。当由一个类实现时,它们可以使用 ObjectOutput 和 ObjectInput 的所有方法写入和读取它们自己的状态。对象负责处理发生的任何版本控制。
枚举常量的序列化方式不同于普通的可序列化或可外部化的对象。枚举常量的序列化形式仅由其名称组成;不传输常量的字段值。为了序列化枚举常量,ObjectOutputStream 写入由常量的名称方法返回的字符串。与其他可序列化或可外部化的对象一样,枚举常量可以用作随后出现在序列化流中的反向引用的目标。枚举常量序列化的过程无法定制;在序列化过程中,枚举类型定义的任何类特定的 writeObject 和 writeReplace 方法都将被忽略。同样,任何 serialPersistentFields 或 serialVersionUID 字段声明也将被忽略——所有枚举类型都具有固定的 serialVersionUID 0L。
原始数据(不包括可序列化字段和可外部化数据)以块数据记录的形式写入 ObjectOutputStream。块数据记录由标题和数据组成。块数据标头由标记和标头后面的字节数组成。连续的原始数据写入被合并到一个块数据记录中。用于块数据记录的块因子将为 1024 字节。每个块数据记录将被填充到 1024 字节,或者在块数据模式终止时被写入。调用 ObjectOutputStream 方法 writeObject、defaultWriteObject 和 writeFields 最初会终止任何现有的块数据记录。
记录的序列化方式不同于普通的可序列化或可外部化的对象,请参阅 记录序列化 。
- 自从:
- 1.1
- 参见:
-
内部类总结
内部类 -
字段摘要
在接口 java.io.ObjectStreamConstants 中声明的字段
baseWireHandle, PROTOCOL_VERSION_1, PROTOCOL_VERSION_2, SC_BLOCK_DATA, SC_ENUM, SC_EXTERNALIZABLE, SC_SERIALIZABLE, SC_WRITE_METHOD, SERIAL_FILTER_PERMISSION, 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 实现使用的私有数据。创建一个写入指定 OutputStream 的 ObjectOutputStream。 -
方法总结
修饰符和类型方法描述protected voidannotateClass(Class<?> cl) 子类可以实现此方法以允许将类数据存储在流中。protected voidannotateProxyClass(Class<?> cl) 子类可以实现此方法以将自定义数据与动态代理类的描述符一起存储在流中。voidclose()关闭流。void将当前类的非静态和非瞬态字段写入此流。protected voiddrain()清空 ObjectOutputStream 中的所有缓冲数据。protected booleanenableReplaceObject(boolean enable) 使流能够替换写入流的对象。voidflush()冲洗流。检索用于缓冲要写入流的持久字段的对象。protected ObjectreplaceObject(Object obj) 此方法将允许 ObjectOutputStream 的受信任子类在序列化期间用一个对象替换另一个对象。voidreset()重置将忽略已写入流的任何对象的状态。voiduseProtocolVersion(int version) 指定写入流时要使用的流协议版本。voidwrite(byte[] buf) 写入一个字节数组。voidwrite(byte[] buf, int off, int len) 写入一个字节子数组。voidwrite(int val) 写入一个字节。voidwriteBoolean(boolean val) 写入一个boolean。voidwriteByte(int val) 写入一个 8 位字节。voidwriteBytes(String str) 将 String 作为字节序列写入。voidwriteChar(int val) 写入 16 位字符。voidwriteChars(String str) 将 String 作为字符序列写入。protected void将指定的类描述符写入 ObjectOutputStream。voidwriteDouble(double val) 写入 64 位双精度数。void将缓冲字段写入流。voidwriteFloat(float val) 写入 32 位浮点数。voidwriteInt(int val) 写入 32 位 int。voidwriteLong(long val) 写入 64 位长。final voidwriteObject(Object obj) 将指定对象写入 ObjectOutputStream。protected void子类用于重写默认 writeObject 方法的方法。voidwriteShort(int val) 写一个 16 位短。protected void提供了 writeStreamHeader 方法,因此子类可以将自己的标头附加或添加到流中。voidwriteUnshared(Object obj) 将“非共享”对象写入 ObjectOutputStream。void以 修改后的 UTF-8 格式写入此字符串的原始数据。在类 java.io.OutputStream 中声明的方法
nullOutputStream
-
构造方法详细信息
-
ObjectOutputStream
创建一个写入指定 OutputStream 的 ObjectOutputStream。此构造方法将序列化流标头写入基础流;调用者可能希望立即刷新流以确保用于接收 ObjectInputStreams 的构造方法在读取标头时不会阻塞。重写 ObjectOutputStream.putFields 或 ObjectOutputStream.writeUnshared 方法的子类的构造方法直接或间接调用时,此构造方法将检查“enableSubclassImplementation”SerializablePermission 。
- 参数:
out- 要写入的输出流- 抛出:
IOException- 如果在写入流头时发生 I/O 错误SecurityException- 如果不受信任的子类非法覆盖安全敏感方法NullPointerException- 如果out是null- 自从:
- 1.4
- 参见:
-
ObjectOutputStream
为完全重新实现 ObjectOutputStream 的子类提供一种方法,使其不必分配仅由该 ObjectOutputStream 实现使用的私有数据。如果安装了安全管理器,此方法首先调用具有
SerializablePermission("enableSubclassImplementation")权限的安全管理器的checkPermission方法以确保可以启用子类化。- 抛出:
SecurityException- 如果安全管理器存在且其checkPermission方法拒绝启用子类化。IOException- 如果在创建此流时发生 I/O 错误- 参见:
-
-
方法详情
-
useProtocolVersion
指定写入流时要使用的流协议版本。此例程提供一个挂钩,使当前版本的序列化能够以向后兼容流格式的先前版本的格式写入。
将尽一切努力避免引入额外的向后不兼容性;然而,有时别无选择。
- 参数:
version- 使用来自 java.io.ObjectStreamConstants 的 ProtocolVersion。- 抛出:
IllegalStateException- 如果在任何对象被序列化后调用。IllegalArgumentException- 如果传入的版本无效。IOException- 如果发生 I/O 错误- 自从:
- 1.2
- 参见:
-
writeObject
将指定对象写入 ObjectOutputStream。对象的类、类的签名以及类及其所有超类型的非瞬态和非静态字段的值都被写入。可以使用 writeObject 和 readObject 方法重写类的默认序列化。此对象引用的对象被传递地写入,以便可以通过 ObjectInputStream 重建对象的完整等效图。OutputStream 问题和不应序列化的类会抛出异常。所有异常对于处于不确定状态的 OutputStream 都是致命的,并且由调用者忽略或恢复流状态。
- 指定者:
writeObject在接口ObjectOutput中- 参数:
obj- 要写入的对象- 抛出:
InvalidClassException- 序列化使用的类有问题。NotSerializableException- 某些要序列化的对象未实现 java.io.Serializable 接口。IOException- 底层 OutputStream 抛出的任何异常。
-
writeObjectOverride
子类用于重写默认 writeObject 方法的方法。此方法由使用受保护的无参数构造方法构造 ObjectOutputStream 的 ObjectOutputStream 的受信任子类调用。子类应提供带有修饰符“final”的重写方法。- 参数:
obj- 要写入底层流的对象- 抛出:
IOException- 如果写入底层流时出现 I/O 错误- 自从:
- 1.2
- 参见:
-
defaultWriteObject
将当前类的非静态和非瞬态字段写入此流。这只能从正在序列化的类的 writeObject 方法中调用。如果以其他方式调用,它将抛出 NotActiveException。- 抛出:
IOException- 如果在写入底层OutputStream时发生 I/O 错误
-
putFields
检索用于缓冲要写入流的持久字段的对象。当调用 writeFields 方法时,字段将被写入流。- 返回:
- 包含可序列化字段的类 Putfield 的实例
- 抛出:
IOException- 如果发生 I/O 错误- 自从:
- 1.2
-
writeFields
将缓冲字段写入流。- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误NotActiveException- 在未调用类 writeObject 方法写入对象状态时调用。- 自从:
- 1.2
-
reset
重置将忽略已写入流的任何对象的状态。状态重置为与新的 ObjectOutputStream 相同。流中的当前点被标记为重置,因此相应的 ObjectInputStream 将在同一点重置。先前写入流的对象将不会被称为已经在流中。它们将再次写入流中。- 抛出:
IOException- 如果在序列化对象时调用了 reset()。
-
annotateClass
子类可以实现此方法以允许将类数据存储在流中。默认情况下,此方法不执行任何操作。 ObjectInputStream中对应的方法是resolveClass。对于流中的每个唯一类,此方法只调用一次。类名和签名将已经写入流中。此方法可以自由使用 ObjectOutputStream 来保存它认为合适的类的任何表示(例如,类文件的字节)。 ObjectInputStream对应子类中的resolveClass方法必须读取和使用annotateClass写入的任何数据或对象。- 参数:
cl- 为其注释自定义数据的类- 抛出:
IOException- 底层 OutputStream 抛出的任何异常。
-
annotateProxyClass
子类可以实现此方法以将自定义数据与动态代理类的描述符一起存储在流中。对于流中的每个唯一代理类描述符,只调用一次此方法。
ObjectOutputStream中此方法的默认实现不执行任何操作。ObjectInputStream中对应的方法是resolveProxyClass。对于覆盖此方法的ObjectOutputStream的给定子类,ObjectInputStream相应子类中的resolveProxyClass方法必须读取由annotateProxyClass写入的任何数据或对象。- 参数:
cl- 用于注释自定义数据的代理类- 抛出:
IOException- 底层OutputStream抛出的任何异常- 自从:
- 1.3
- 参见:
-
replaceObject
此方法将允许 ObjectOutputStream 的受信任子类在序列化期间用一个对象替换另一个对象。在调用 enableReplaceObject 之前,替换对象是禁用的。 enableReplaceObject 方法检查请求进行替换的流是否可信。写入序列化流的每个对象的第一次出现被传递给 replaceObject。对该对象的后续引用将替换为对 replaceObject 的原始调用所返回的对象。为确保对象的私有状态不会无意中暴露,只有受信任的流可以使用 replaceObject。ObjectOutputStream.writeObject 方法采用 Object 类型(与 Serializable 类型相反)的参数,以允许将不可序列化对象替换为可序列化对象的情况。
当子类替换对象时,它必须确保在反序列化期间必须进行互补替换,或者替换的对象与将存储引用的每个字段兼容。类型不是字段或数组元素类型的子类的对象通过引发异常中止序列化,并且不存储该对象。
当第一次遇到每个对象时,只调用一次此方法。对该对象的所有后续引用都将重定向到新对象。此方法应返回要替换的对象或原始对象。
Null 可以作为要替换的对象返回,但可能会在包含对原始对象的引用的类中导致 NullReferenceException,因为它们可能需要一个对象而不是 null。
- 参数:
obj- 要替换的对象- 返回:
- 替换指定对象的替代对象
- 抛出:
IOException- 底层 OutputStream 抛出的任何异常。
-
enableReplaceObject
使流能够替换写入流的对象。启用后,将为每个被序列化的对象调用replaceObject(java.lang.Object)方法。如果当前未启用对象替换,并且
enable为真,并且安装了安全管理器,则此方法首先以SerializablePermission("enableSubstitution")权限调用安全管理器的checkPermission方法,以确保允许调用者启用流来进行对象替换写入流。- 参数:
enable- 为每个被序列化的对象启用replaceObject时为真- 返回:
- 调用此方法之前的先前设置
- 抛出:
SecurityException- 如果安全管理器存在且其checkPermission方法拒绝启用流来替换写入流的对象。- 参见:
-
writeStreamHeader
提供了 writeStreamHeader 方法,因此子类可以将自己的标头附加或添加到流中。它将幻数和版本写入流。- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeClassDescriptor
将指定的类描述符写入 ObjectOutputStream。类描述符用于标识写入流的对象的类。 ObjectOutputStream 的子类可以覆盖此方法以自定义将类描述符写入序列化流的方式。然后应覆盖 ObjectInputStream 中的相应方法readClassDescriptor以从其自定义流表示重构类描述符。默认情况下,此方法根据 Java 对象序列化规范 中定义的格式写入类描述符。请注意,仅当 ObjectOutputStream 未使用旧的序列化流格式(通过调用 ObjectOutputStream 的
useProtocolVersion方法设置)时,才会调用此方法。如果此序列化流使用旧格式 (PROTOCOL_VERSION_1),则类描述符将以无法覆盖或自定义的方式在内部写入。- 参数:
desc- 写入流的类描述符- 抛出:
IOException- 如果发生 I/O 错误。- 自从:
- 1.3
- 参见:
-
write
写入一个字节。此方法将阻塞,直到实际写入字节为止。- 指定者:
write在接口DataOutput中- 指定者:
write在接口ObjectOutput中- 指定者:
write在类OutputStream中- 参数:
val- 要写入流的字节- 抛出:
IOException- 如果发生 I/O 错误。
-
write
写入一个字节数组。此方法将阻塞,直到实际写入字节为止。- 指定者:
write在接口DataOutput中- 指定者:
write在接口ObjectOutput中- 重写:
write在类OutputStream中- 参数:
buf- 要写入的数据- 抛出:
IOException- 如果发生 I/O 错误。- 参见:
-
write
写入一个字节子数组。- 指定者:
write在接口DataOutput中- 指定者:
write在接口ObjectOutput中- 重写:
write在类OutputStream中- 参数:
buf- 要写入的数据off- 数据中的起始偏移量len- 写入的字节数- 抛出:
IOException- 如果发生 I/O 错误。特别是,如果输出流关闭,则会抛出IOException。IndexOutOfBoundsException- 如果off为负,len为负,或者len大于b.length - off
-
flush
冲洗流。这将写入任何缓冲的输出字节并刷新到底层流。- 指定者:
flush在接口Flushable中- 指定者:
flush在接口ObjectOutput中- 重写:
flush在类OutputStream中- 抛出:
IOException- 如果发生 I/O 错误。
-
drain
清空 ObjectOutputStream 中的所有缓冲数据。与 flush 类似,但不会将 flush 传播到底层流。- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
close
关闭流。必须调用此方法来释放与流关联的任何资源。- 指定者:
close在接口AutoCloseable中- 指定者:
close在接口Closeable中- 指定者:
close在接口ObjectOutput中- 重写:
close在类OutputStream中- 抛出:
IOException- 如果发生 I/O 错误。
-
writeBoolean
写入一个boolean。- 指定者:
writeBoolean在接口DataOutput中- 参数:
val- 要写入的boolean- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeByte
写入一个 8 位字节。- 指定者:
writeByte在接口DataOutput中- 参数:
val- 要写入的字节值- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeShort
写一个 16 位短。- 指定者:
writeShort在接口DataOutput中- 参数:
val- 要写入的短值- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeChar
写入 16 位字符。- 指定者:
writeChar在接口DataOutput中- 参数:
val- 要写入的字符值- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeInt
写入 32 位 int。- 指定者:
writeInt在接口DataOutput中- 参数:
val- 要写入的整数值- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeLong
写入 64 位长。- 指定者:
writeLong在接口DataOutput中- 参数:
val- 要写入的 long 值- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeFloat
写入 32 位浮点数。- 指定者:
writeFloat在接口DataOutput中- 参数:
val- 要写入的浮点值- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeDouble
写入 64 位双精度数。- 指定者:
writeDouble在接口DataOutput中- 参数:
val- 要写入的双精度值- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeBytes
将 String 作为字节序列写入。- 指定者:
writeBytes在接口DataOutput中- 参数:
str- 要写入的字节串- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeChars
将 String 作为字符序列写入。- 指定者:
writeChars在接口DataOutput中- 参数:
str- 要写入的字符串- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-
writeUTF
以 修改后的 UTF-8 格式写入此字符串的原始数据。请注意,将字符串作为原始数据或作为对象写入流中存在显着差异。 writeObject 写入的 String 实例最初作为 String 写入流中。未来的 writeObject() 调用将对字符串的引用写入流中。- 指定者:
writeUTF在接口DataOutput中- 参数:
str- 要写入的字符串- 抛出:
IOException- 如果在写入底层流时发生 I/O 错误
-