共计 1316 个字符,预计需要花费 4 分钟才能阅读完成。
对象流
正如数据流支持原始数据类型的 I / O 一样,对象流也支持对象的 I /O,大多数(但不是全部)标准类支持其对象的序列化,那些是实现标记接口 Serializable 的。
对象流类是 ObjectInputStream 和 ObjectOutputStream,这些类实现 ObjectInput 和 ObjectOutput,它们是 DataInput 和 DataOutput 的子接口。这意味着数据流中涵盖的所有原始数据 I / O 方法也在对象流中实现,因此,对象流可以包含原始值和对象值的混合。ObjectStreams 示例说明了这一点,ObjectStreams 创建与 DataStreams 相同的应用程序,并进行了一些更改,首先,价格现在是 BigDecimal 对象,以更好地代表小数值,其次,将 Calendar 对象写入数据文件,指示发票日期。
如果 readObject() 没有返回预期的对象类型,则尝试将其强制转换为正确的类型可能会抛出 ClassNotFoundException,在这个简单的例子中,这不可能发生,因此我们不会尝试捕获异常,相反,我们通过向 main 方法的 throws 子句添加 ClassNotFoundException 来通知编译器我们已经意识到了这个问题。
复杂对象的输出和输入
writeObject 和 readObject 方法易于使用,但它们包含一些非常复杂的对象管理逻辑,这对像 Calendar 这样的类来说并不重要,它只封装了原始值,但是许多对象包含对其他对象的引用,如果 readObject 是要从流重建一个对象,它必须能够重建原始对象所引用的所有对象,这些附加对象可能有自己的引用,依此类推。在这种情况下,writeObject 遍历整个对象引用网络,并将该网络中的所有对象写入流,因此,对 writeObject 的单个调用可能导致将大量对象写入流。
下图演示了这一点,其中调用 writeObject 来写入名为 a 的单个对象,该对象包含对象 b 和 c 的引用,而 b 包含对 d 和 e 的引用,调用 writeobject(a) 不仅写入 a,而且写入重建 a 所需的所有对象,因此该网络中的其他四个对象也被写入。当 readObject 读回 a 时,也会读回其他四个对象,并保留所有原始对象引用。
你可能想知道如果同一个流上的两个对象都包含对单个对象的引用会发生什么,当他们被回读时,他们都会引用一个对象吗?答案是肯定的。一个流只能包含一个对象的副本,尽管它可以包含对该对象的任意数量的引用,因此,如果你明确地将对象写入流两次,那么你实际上只写入了两次引用,例如,如果以下代码将对象 ob 写入流两次:
Object ob = new Object();
out.writeObject(ob);
out.writeObject(ob);
每个 writeObject 都必须与 readObject 匹配,因此读回流的代码将如下所示:
Object ob1 = in.readObject();
Object ob2 = in.readObject();
这产生两个变量 ob1 和 ob2,它们是对单个对象的引用。
但是,如果将单个对象写入两个不同的流,则会有效地复制它 — 读取两个流的单个程序将看到两个不同的对象。
上一篇:数据流