不,您不会获得超出必要数量的实例。这是因为在内部,ObjectOutputStream
在“句柄表”中注册每个曾经序列化的对象。因此,即使多次调用 writeObject(Object),
同一个对象也永远不会被写入两次!C
ObjectOutputStream
的 API 文档:
(...)使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象的图形还原到与写入原始对象时相同的形状。(...)
考虑以下代码(假设 和 是可序列化的
,并且两者兼而有之,并且有一个指向 以下实例的非瞬态字段):A
B
C
A
B
c
C
A a = new A();
B b = new B();
C c = new C();
a.c = c;
b.c = c;
out.writeObject(a); // writes a and c
out.writeObject(b); // writes b and the handle to c
现在让我们读取这两个对象:
A a2 = (A)in.readObject(); // reads a and c
B b2 = (B)in.readObject(); // reads b and handle to c, so b.c points to existing c
// now this is true: a2.c == b2.c
如果您直接将对象写入两次,这也有效,例如:
A a = new A();
out.writeObject(a); // writes a
out.writeObject(a); // writes handle to a
第二个将只写入句柄,而不写入对象本身。这意味着当您再次反序列化对象时,您将不会得到以下两个实例:writeObject
A
A a1 = (A)in.readObject(); // reads a
A a2 = (A)in.readObject(); // reads the handle and returns existing a
// now this is true: a1 == a2
通过调用 reset
,您可以清除“句柄表”,以便流的行为类似于新创建的流。
请注意,a 还提供了一个方法 writeObjectUnshared(Object
),该方法始终将对象作为新的唯一对象写入流。ObjectOutputStream