Java序列化和重复对象 [英] Java serialization and duplicate objects

查看:255
本文介绍了Java序列化和重复对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下设置:

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

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

public class C {}

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

A's and B's cSet might have references to same C instances. I want to serialize A and B such that upon deserialization I don't have duplicate C objects. Will Java know how to do the right thing if I serialize/deserialize it into the same ObjectOutputStream, or might I end up with more C instances than I started out with?

推荐答案

不,您将不会获得超过必要的 C 的更多实例。这是因为在内部, ObjectOutputStream 在句柄表中注册每个序列化对象。所以即使是多次调用 writeObject(Object) ,同一个对象永远不会写两次!

No, you won't get more instances of C than necessary. That's because internally, the ObjectOutputStream registers every ever serialized object in a 'handle table'. So even across multiple invocations of writeObject(Object), the same object will never be written twice!

ObjectOutputStream


(.. 。)使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象图形恢复为与写入原始图像时相同的形状。 (...)

(...) 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. (...)

考虑这段代码(假设 A B C Serializable 和两者, A B 有一个非瞬态字段 c 指向<的实例code> C ):

Consider this code (assuming A, B and C are Serializable and both, A and B have a non-transient field c pointing to an instance of 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

现在让我们读取两个对象:

Now let's read both objects:

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

如果你直接写一个对象两次,这也有效,例如:

This also works if you directly write an object twice, e.g.:

A a = new A();
out.writeObject(a); // writes a
out.writeObject(a); // writes handle to a

第二个 writeObject 只会写句柄,而不是对象本身。这意味着当您再次反序列化对象时,您将不会得到两个 A 的实例:

The second writeObject will only write the handle, not the object itself. That means when you deserialize the objects again, you won't get two instances of 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

通过调用 重置 ,您可以清除句柄表,使流的行为与新创建的一样。

By calling reset, you can clear the 'handle table' so that the stream behaves like newly created.

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

Note that a ObjectOutputStream also offers a method writeObjectUnshared(Object) that always writes an object as a new unique object to the stream.

这篇关于Java序列化和重复对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆