The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
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
. ObjectInputStream
和ObjectOutputStream
。These classes implement 这些类实现ObjectInput
and ObjectOutput
, which are subinterfaces of DataInput
and DataOutput
. ObjectInput
和ObjectOutput
,它们是DataInput
和DataOutput
的子接口。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 首先,价格现在是BigDecimal
objects, 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()
未返回预期的对象类型,尝试将其强制转换为正确的类型可能会引发ClassNotFoundException
。In 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
来通知编译器我们已经注意到了这个问题。
The writeObject
and readObject
methods are simple to use, but they contain some very sophisticated object management logic. writeObject
和readObject
方法使用简单,但它们包含一些非常复杂的对象管理逻辑。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. 此对象包含对对象b和c的引用,而b包含对d和e的引用。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
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.ob1
和ob2
,它们是对单个对象的引用。
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.但是,如果一个对象被写入两个不同的流,它将被有效地复制一个程序读回两个流将看到两个不同的对象。