Object Streams

就像数据流支持原始数据类型的 I/O 一样,对象流也支持对象的 I/O。大多数(但不是全部)标准类支持其对象的序列化。那些确实实现了标记interfaceSerializable的对象。

对象流类是ObjectInputStreamObjectOutputStream。这些类实现ObjectInputObjectOutput,它们是DataInputDataOutput的子interface。这意味着Data Streams中涵盖的所有原始数据 I/O 方法也都在对象流中实现。因此,对象流可以包含原始值和对象值的混合。 ObjectStreams示例说明了这一点。 ObjectStreams创建与DataStreams相同的应用程序,但有一些更改。首先,价格现在是BigDecimal个对象,以更好地表示分数值。其次,将Calendar对象写入数据文件,指示发票日期。

如果readObject()没有返回预期的对象类型,则try将其转换为正确的类型可能会抛出ClassNotFoundException。在这个简单的示例中,这不可能发生,因此我们不会trycatch异常。相反,我们通过在main方法的throws子句中添加ClassNotFoundException来通知编译器我们已经知道该问题。

复杂对象的输出和 Importing

writeObjectreadObject方法易于使用,但是它们包含一些非常复杂的对象 管理 逻辑。对于像 Calendar 这样的仅封装原始值的类,这并不重要。但是许多对象包含对其他对象的引用。如果readObject要从流中重构对象,则它必须能够重构原始对象所引用的所有对象。这些其他对象可能有自己的引用,依此类推。在这种情况下,writeObject遍历对象引用的整个 Web 并将该 Web 中的所有对象写入流中。因此,一次调用writeObject可以导致将大量对象写入流中。

在下图中演示了这一点,其中调用了writeObject以写入名为 a 的单个对象。该对象包含对对象 bc 的引用,而 b 包含对 de 的引用。调用writeobject(a)不仅会写入 a ,而且还会写入重构 a 所需的所有对象,因此也将写入此 Web 中的其他四个对象。当readObject读回 a 时,其他四个对象也会被读回,并且所有原始对象引用都将保留。

多个引用对象的 I/O

多个引用对象的 I/O

您可能想知道,如果同一流上的两个对象都包含对单个对象的引用,将会发生什么情况。回读它们是否都引用一个对象?答案是“是”。一个流只能包含一个对象的一个副本,尽管它可以包含对该对象的任何数量的引用。因此,如果您将一个对象显式地写入流两次,则实际上仅写入了两次引用。例如,如果以下代码将对象ob两次写入流:

Object ob = new Object();
out.writeObject(ob);
out.writeObject(ob);

每个writeObject必须由readObject匹配,因此读回流的代码将类似于以下内容:

Object ob1 = in.readObject();
Object ob2 = in.readObject();

这将导致两个变量ob1ob2,它们是对单个对象的引用。

但是,如果将单个对象写入两个不同的流,则该对象将被有效地复制-读回两个流的单个程序将看到两个不同的对象。