gpt4 book ai didi

Java序列化和重复对象

转载 作者:搜寻专家 更新时间:2023-10-30 19:58:50 25 4
gpt4 key购买 nike

我有以下设置:

public class A {
private Set<C> cSet;
}

public class B {
private Set<C> cSet;
}

public class C {}

A 和 B 的 cSet 可能引用相同的 C 实例。我想序列化 A 和 B,这样在反序列化时我就没有重复的 C 对象。如果我将它序列化/反序列化到同一个 ObjectOutputStream 中,Java 是否知道如何做正确的事情,或者我最终可能会得到比开始时更多的 C 实例?

最佳答案

不,您不会获得不必要的 C 实例。那是因为在内部,ObjectOutputStream在“句柄表”中注册每个曾经序列化的对象。因此,即使多次调用 writeObject(Object) ,同一个对象永远不会被写两次!

ObjectOutputStream 的 API 文档:

(...) Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written. (...)

考虑此代码(假设 ABCSerializable 并且两者都是,AB 有一个非 transient 字段 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 ,您可以清除“句柄表”,以便流的行为就像新创建的一样。

请注意,ObjectOutputStream 还提供了一个方法 writeObjectUnshared(Object)始终将对象作为新的唯一对象写入流。

关于Java序列化和重复对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20076784/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com