- java.lang.Object
-
- java.io.OutputStream
-
- java.io.ObjectOutputStream
-
- All Implemented Interfaces:
-
Closeable
,DataOutput
,Flushable
,ObjectOutput
,ObjectStreamConstants
,AutoCloseable
public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants
ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。只有支持java.io.Serializable接口的对象才能写入流中。 每个可序列化对象的类被编码,包括类的类名和签名,对象的字段和数组的值以及从初始对象引用的任何其他对象的关闭。
方法writeObject用于将一个对象写入流中。 任何对象,包括字符串和数组,都是用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接口的对象的字段。 不可序列化的对象的子类可以是可序列化的。 在这种情况下,非可序列化类必须有一个无参数构造函数,以允许其字段被初始化。 在这种情况下,子类有责任保存并恢复不可序列化类的状态。 通常情况下,该类的字段是可访问的(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
- 另请参见:
-
DataOutput
,ObjectInputStream
,Serializable
,Externalizable
, Object Serialization Specification, Section 2, Object Output Classes
-
-
Nested Class Summary
Nested Classes Modifier and Type Class 描述 static class
ObjectOutputStream.PutField
提供对要写入ObjectOutput的持久字段的编程访问。
-
Field Summary
-
Fields inherited from interface 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
-
-
构造方法摘要
构造方法 Modifier Constructor 描述 protected
ObjectOutputStream()
为完全重新实现ObjectOutputStream的子类提供一种方法,不必分配刚刚被ObjectOutputStream实现使用的私有数据。ObjectOutputStream(OutputStream out)
创建一个写入指定的OutputStream的ObjectOutputStream。
-
方法摘要
所有方法 接口方法 具体的方法 Modifier and Type 方法 描述 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)
写入一个字节数组。void
write(byte[] buf, int off, int len)
写入一个子字节数组。void
write(int val)
写一个字节。void
writeBoolean(boolean val)
写一个布尔值。void
writeByte(int val)
写入一个8位字节。void
writeBytes(String str)
写一个字符串作为字节序列。void
writeChar(int val)
写一个16位的字符。void
writeChars(String str)
写一个字符串作为一系列的字符。protected void
writeClassDescriptor(ObjectStreamClass desc)
将指定的类描述符写入ObjectOutputStream。void
writeDouble(double val)
写一个64位的双倍。void
writeFields()
将缓冲的字段写入流。void
writeFloat(float val)
写一个32位浮点数。void
writeInt(int val)
写一个32位int。void
writeLong(long val)
写一个64位长void
writeObject(Object obj)
将指定的对象写入ObjectOutputStream。protected void
writeObjectOverride(Object obj)
子类使用的方法来覆盖默认的writeObject方法。void
writeShort(int val)
写一个16位短。protected void
writeStreamHeader()
提供了writeStreamHeader方法,因此子类可以在流中附加或预先添加自己的头。void
writeUnshared(Object obj)
将“非共享”对象写入ObjectOutputStream。void
writeUTF(String str)
此字符串的原始数据写入格式为 modified UTF-8 。
-
-
-
构造方法详细信息
-
ObjectOutputStream
public ObjectOutputStream(OutputStream out) throws IOException
创建一个写入指定的OutputStream的ObjectOutputStream。 该构造函数将序列化流头写入底层流; 调用者可能希望立即刷新流,以确保在读取头部时接收ObjectInputStreams的构造函数不会阻塞。如果安装了一个安全管理器,那么这个构造函数会在被覆盖ObjectOutputStream.putFields或ObjectOutputStream.writeUnshared方法的子类的构造函数直接或间接调用时检查“enableSubclassImplementation”SerializablePermission。
- 参数
-
out
- 输出流写入 - 异常
-
IOException
- 如果在写入流标题时发生I / O错误 -
SecurityException
- 如果不可信子类非法覆盖安全敏感方法 -
NullPointerException
- 如果out
是null
- 从以下版本开始:
- 1.4
- 另请参见:
-
ObjectOutputStream()
,putFields()
,ObjectInputStream(InputStream)
-
ObjectOutputStream
protected ObjectOutputStream() throws IOException, SecurityException
为完全重新实现ObjectOutputStream的子类提供一种方法,不必分配刚刚被ObjectOutputStream实现使用的私有数据。如果安装了安全管理器,则该方法首先使用
SerializablePermission("enableSubclassImplementation")
权限调用安全管理器的checkPermission
方法,以确保启用子类化。- 异常
-
SecurityException
- 如果安全管理器存在,并且其checkPermission
方法拒绝启用子类化。 -
IOException
- 如果在创建此流时发生I / O错误 - 另请参见:
-
SecurityManager.checkPermission(java.security.Permission)
,SerializablePermission
-
-
方法详细信息
-
useProtocolVersion
public void useProtocolVersion(int version) throws IOException
指定在编写流时使用的流协议版本。此例程提供了一个钩子,以使当前版本的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是致命的,它将处于不确定状态,由呼叫者来忽略或恢复流状态。
- Specified by:
-
writeObject
在接口ObjectOutput
- 参数
-
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相同,只是它始终将给定对象作为新的唯一对象写入流中(而不是指向之前的序列化实例的反向引用)。 特别:- 通过writeUnshared编写的对象总是以与新出现的对象(尚未写入流的对象)相同的方式进行序列化,而不管以前是否已经写过该对象。
- 如果writeObject用于写入先前使用writeUnshared写入的对象,则先前的writeUnshared操作将被视为单独对象的写入。 换句话说,ObjectOutputStream永远不会生成对由writeUnshared调用写入的对象数据的反向引用。
ObjectOutputStream子类覆盖此方法只能在拥有“enableSubclassImplementation”SerializablePermission的安全上下文中构建; 任何尝试在没有此权限的情况下实例化此类子类将导致抛出SecurityException。
- 参数
-
obj
- 要写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方法时,字段将被写入流。- 结果
- 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相同。 流中的当前点被标记为重置,所以相应的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
。 对于覆盖此方法的resolveProxyClass
的给定子类,ObjectOutputStream
的相应子类中的ObjectInputStream
必须读取由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类型相反),以允许将非可序列化对象替换为可序列化对象的情况。
当子类替换对象时,必须确保在反序列化期间必须进行补充替换,或者替换对象与要存储引用的每个字段兼容。 类型不是字段或数组元素类型的子类的对象通过引发异常终止序列化,并且不存储该对象。
当首次遇到每个对象时,此方法仅调用一次。 对对象的所有后续引用将被重定向到新对象。 该方法应该返回要替换的对象或原始对象。
Null可以作为要替换的对象返回,但是可能会在包含对原始对象的引用的类中引起NullReferenceException,因为它们可能期望一个对象而不是null。
- 参数
-
obj
- 要替换的对象 - 结果
- 代替指定的替代对象
- 异常
-
IOException
- 底层OutputStream抛出的任何异常。
-
enableReplaceObject
protected boolean enableReplaceObject(boolean enable) throws SecurityException
启用流来替代写入流的对象。 启用时,为每个被序列化的对象调用replaceObject(java.lang.Object)
方法。如果对象替换当前未启用,并
enable
是真实的,并且安装了安全管理器,此方法首先调用安全管理器的checkPermission
方法与SerializablePermission("enableSubstitution")
权限,以确保调用者被允许使流对象进行替换的写入流。- 参数
-
enable
- 允许对串行化的每个对象使用replaceObject
- 结果
- 此方法被调用之前的前一个设置
- 异常
-
SecurityException
- 如果安全管理器存在,并且其checkPermission
方法拒绝使流能够替换写入流的对象。 - 另请参见:
-
SecurityManager.checkPermission(java.security.Permission)
,SerializablePermission
-
writeStreamHeader
protected void writeStreamHeader() throws IOException
提供了writeStreamHeader方法,因此子类可以在流中附加或预先添加自己的头。 它将魔术数字和版本写入流。- 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeClassDescriptor
protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException
将指定的类描述符写入ObjectOutputStream。 类描述符用于标识写入流的对象类。 ObjectOutputStream的子类可以覆盖此方法来自定义类描述符写入序列化流的方式。 然后应该覆盖ObjectInputStreamreadClassDescriptor
的相应方法,readClassDescriptor
从其自定义流表示中重新构建类描述符。 默认情况下,此方法根据对象序列化规范中定义的格式编写类描述符。请注意,只有当ObjectOutputStream不使用旧的序列化流格式(通过调用ObjectOutputStream的
useProtocolVersion
方法设置)时,useProtocolVersion
调用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
写一个字节。 该方法将阻塞,直到字节实际写入。- Specified by:
-
write
在接口DataOutput
- Specified by:
-
write
在接口ObjectOutput
- Specified by:
-
write
在OutputStream
- 参数
-
val
-val
的字节 - 异常
-
IOException
- 如果发生I / O错误。
-
write
public void write(byte[] buf) throws IOException
写入一个字节数组。 该方法将阻塞直到字节实际写入。- Specified by:
-
write
在接口DataOutput
- Specified by:
-
write
在接口ObjectOutput
- 重写:
-
write
在OutputStream
- 参数
-
buf
- 要写入的数据 - 异常
-
IOException
- 如果发生I / O错误。 - 另请参见:
-
OutputStream.write(byte[], int, int)
-
write
public void write(byte[] buf, int off, int len) throws IOException
写入一个子字节数组。- Specified by:
-
write
在接口DataOutput
- Specified by:
-
write
在接口ObjectOutput
- 重写:
-
write
在OutputStream
- 参数
-
buf
- 要写入的数据 -
off
- 数据中的起始偏移量 -
len
- 写入的字节数 - 异常
-
IOException
- 如果发生I / O错误。
-
flush
public void flush() throws IOException
刷新流。 这将写入任何缓冲的输出字节并刷新到底层流。- Specified by:
-
flush
在接口Flushable
- Specified by:
-
flush
在接口ObjectOutput
- 重写:
-
flush
在OutputStream
- 异常
-
IOException
- 如果发生I / O错误。
-
drain
protected void drain() throws IOException
排除ObjectOutputStream中的缓冲数据。 类似于flush,但不会将flush传播到底层流。- 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
close
public void close() throws IOException
关闭流。 必须调用此方法以释放与流相关联的任何资源。- Specified by:
-
close
在接口AutoCloseable
- Specified by:
-
close
在接口Closeable
- Specified by:
-
close
在接口ObjectOutput
- 重写:
-
close
在OutputStream
- 异常
-
IOException
- 如果发生I / O错误。
-
writeBoolean
public void writeBoolean(boolean val) throws IOException
写一个布尔值。- Specified by:
-
writeBoolean
在接口DataOutput
- 参数
-
val
- 要写入的布尔值 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeByte
public void writeByte(int val) throws IOException
写入一个8位字节。- Specified by:
-
writeByte
接口DataOutput
- 参数
-
val
- 要写入的字节值 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeShort
public void writeShort(int val) throws IOException
写一个16位短。- Specified by:
-
writeShort
在接口DataOutput
- 参数
-
val
-val
的短价值 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeChar
public void writeChar(int val) throws IOException
写一个16位的字符。- Specified by:
-
writeChar
在接口DataOutput
- 参数
-
val
- 要写入的char值 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeInt
public void writeInt(int val) throws IOException
写一个32位int。- Specified by:
-
writeInt
在接口DataOutput
- 参数
-
val
- 要写入的整数值 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeLong
public void writeLong(long val) throws IOException
写一个64位长- Specified by:
-
writeLong
在接口DataOutput
- 参数
-
val
-val
的长的价值 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeFloat
public void writeFloat(float val) throws IOException
写一个32位浮点数。- Specified by:
-
writeFloat
在接口DataOutput
- 参数
-
val
- 要写入的浮点值 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeDouble
public void writeDouble(double val) throws IOException
写一个64位的双倍。- Specified by:
-
writeDouble
在接口DataOutput
- 参数
-
val
- 要写入的双重值 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeBytes
public void writeBytes(String str) throws IOException
写一个字符串作为字节序列。- Specified by:
-
writeBytes
在接口DataOutput
- 参数
-
str
- 要写入的字节串 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeChars
public void writeChars(String str) throws IOException
写一个字符串作为一系列的字符。- Specified by:
-
writeChars
在接口DataOutput
- 参数
-
str
- 要写入的字符串 - 异常
-
IOException
- 如果在写入底层流时发生I / O错误
-
writeUTF
public void writeUTF(String str) throws IOException
此字符串的原始数据写入格式为modified UTF-8 。 请注意,将字符串写入流中作为原始数据或作为对象有重大差异。 由writeObject写的String实例最初作为String写入流中。 未来的writeObject()会将对字符串的引用调用到流中。- Specified by:
-
writeUTF
在接口DataOutput
- 参数
-
str
- 要写入的字符串 - 异常
-
IOException
- if I/O errors occur while writing to the underlying stream
-
-