use*_*725 13 java serialization duplicates
我有以下设置:
public class A {
private Set<C> cSet;
}
public class B {
private Set<C> cSet;
}
public class C {}
Run Code Online (Sandbox Code Playgroud)
A和B的cSet可能引用了相同的C实例.我想序列化A和B,以便在反序列化时我没有重复的C对象.如果我将它序列化/反序列化到同一个ObjectOutputStream中,Java是否知道如何做正确的事情,或者我最终会得到比我开始时更多的C实例?
isn*_*bad 14
不,你不会得到C超过必要的更多实例.那是因为在内部,ObjectOutputStream寄存器中每个序列化对象都在"句柄表"中.因此,即使在多次调用中writeObject(Object),同一个对象也永远不会被写入两次!
API文档ObjectOutputStream:
(...)使用参考共享机制对单个对象的多个引用进行编码,以便可以将对象图形恢复为与写入原始图像时相同的形状.(......)
考虑下面的代码(假设A,B和C是Serializable与两者,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
Run Code Online (Sandbox Code Playgroud)
现在让我们读两个对象:
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
Run Code Online (Sandbox Code Playgroud)
如果你直接写一个对象两次,这也有效,例如:
A a = new A();
out.writeObject(a); // writes a
out.writeObject(a); // writes handle to a
Run Code Online (Sandbox Code Playgroud)
第二个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
Run Code Online (Sandbox Code Playgroud)
通过调用reset,您可以清除"句柄表",以便流的行为类似于新创建的.
请注意,a ObjectOutputStream还提供了一种writeObjectUnshared(Object)始终将对象作为新的唯一对象写入流的方法.
| 归档时间: |
|
| 查看次数: |
1197 次 |
| 最近记录: |