Documentation

The Java™ Tutorials
Hide TOC
Object Streams对象流
Trail: Essential Java Classes
Lesson: Basic I/O
Section: I/O Streams

Object Streams对象流

Just as data streams support I/O of primitive data types, object streams support I/O of objects. 正如数据流支持基本数据类型的I/O一样,对象流也支持对象的I/O。Most, but not all, standard classes support serialization of their objects. 大多数(但不是所有)标准类都支持对象的序列化。Those that do implement the marker interface Serializable.那些实现了标记接口Serializable的。

The object stream classes are ObjectInputStream and ObjectOutputStream. 对象流类是ObjectInputStreamObjectOutputStreamThese classes implement ObjectInput and ObjectOutput, which are subinterfaces of DataInput and DataOutput. 这些类实现ObjectInputObjectOutput,它们是DataInputDataOutput的子接口。That means that all the primitive data I/O methods covered in Data Streams are also implemented in object streams. 这意味着数据流中包含的所有基本数据I/O方法也在对象流中实现。So an object stream can contain a mixture of primitive and object values. 因此,对象流可以包含基本值和对象值的混合。The ObjectStreams example illustrates this. ObjectStreams示例说明了这一点。ObjectStreams creates the same application as DataStreams, with a couple of changes. ObjectStreams创建与DataStreams相同的应用程序,只需做一些更改。First, prices are now BigDecimalobjects, to better represent fractional values. 首先,价格现在是BigDecimal对象,以便更好地表示分数。Second, a Calendar object is written to the data file, indicating an invoice date.其次,将Calendar对象写入数据文件,指示发票日期。

If readObject() doesn't return the object type expected, attempting to cast it to the correct type may throw a ClassNotFoundException. 如果readObject()未返回预期的对象类型,尝试将其强制转换为正确的类型可能会引发ClassNotFoundExceptionIn this simple example, that can't happen, so we don't try to catch the exception. 在这个简单的示例中,这是不可能发生的,因此我们不尝试捕获异常。Instead, we notify the compiler that we're aware of the issue by adding ClassNotFoundException to the main method's throws clause.相反,我们通过向main方法的throws子句中添加ClassNotFoundException来通知编译器我们已经注意到了这个问题。

Output and Input of Complex Objects复杂对象的输出和输入

The writeObject and readObject methods are simple to use, but they contain some very sophisticated object management logic. writeObjectreadObject方法使用简单,但它们包含一些非常复杂的对象管理逻辑。This isn't important for a class like Calendar, which just encapsulates primitive values. 这对于像Calendar这样的类来说并不重要,它只封装了基本值。But many objects contain references to other objects. 但许多对象包含对其他对象的引用。If readObject is to reconstitute an object from a stream, it has to be able to reconstitute all of the objects the original object referred to. 如果readObject要从流中重构对象,它必须能够重构原始对象所引用的所有对象。These additional objects might have their own references, and so on. 这些附加对象可能有自己的引用,等等。In this situation, writeObject traverses the entire web of object references and writes all objects in that web onto the stream. 在这种情况下,writeObject遍历对象引用的整个web,并将该web中的所有对象写入流。Thus a single invocation of writeObject can cause a large number of objects to be written to the stream.因此,单次调用writeObject可能会导致大量对象写入流。

This is demonstrated in the following figure, where writeObject is invoked to write a single object named a. 下图演示了这一点,其中调用writeObject来编写名为a的单个对象。This object contains references to objects b and c, while b contains references to d and e. 此对象包含对对象bc的引用,而b包含对de的引用。Invoking writeobject(a) writes not just a, but all the objects necessary to reconstitute a, so the other four objects in this web are written also. 调用writeobject(a)不仅会写入a,还会写入重建a所需的所有对象,因此该web中的其他四个对象也会写入。When a is read back by readObject, the other four objects are read back as well, and all the original object references are preserved.readObject读回一个对象时,其他四个对象也会读回,并且保留所有原始对象引用。

I/O of multiple referred-to objects

I/O of multiple referred-to objects多个引用对象的I/O

You might wonder what happens if two objects on the same stream both contain references to a single object. 您可能想知道,如果同一流中的两个对象都包含对单个对象的引用,会发生什么情况。Will they both refer to a single object when they're read back? 当它们被读回时,它们都会引用一个对象吗?The answer is "yes." 答案是“是的。”A stream can only contain one copy of an object, though it can contain any number of references to it. 流只能包含对象的一个副本,尽管它可以包含对它的任意数量的引用。Thus if you explicitly write an object to a stream twice, you're really writing only the reference twice. 因此,如果显式地将对象写入流两次,那么实际上只写入引用两次。For example, if the following code writes an object ob twice to a stream:例如,如果以下代码将对象ob写入流两次:

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

Each writeObject has to be matched by a readObject, so the code that reads the stream back will look something like this:每个writeObject必须与readObject匹配,因此读回流的代码如下所示:

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

This results in two variables, ob1 and ob2, that are references to a single object.这将产生两个变量ob1ob2,它们是对单个对象的引用。

However, if a single object is written to two different streams, it is effectively duplicated — a single program reading both streams back will see two distinct objects.但是,如果一个对象被写入两个不同的流,它将被有效地复制—一个程序读回两个流将看到两个不同的对象。


Previous page: Data Streams
Next page: File I/O (Featuring NIO.2)