Java序列化和复制对象
我有以下设置:Java序列化和复制对象,java,serialization,duplicates,Java,Serialization,Duplicates,我有以下设置: public class A { private Set<C> cSet; } public class B { private Set<C> cSet; } public class C {} 公共A类{ 私有集cSet; } 公共B级{ 私有集cSet; } 公共类C{} A和B的cSet可能对相同的C实例有引用。我想序列化A和B,这样在反序列化时就不会有重复的C对象。如果我将Java序列化/反序列化到同一个ObjectOutputSt
public class A {
private Set<C> cSet;
}
public class B {
private Set<C> cSet;
}
public class C {}
公共A类{
私有集cSet;
}
公共B级{
私有集cSet;
}
公共类C{}
A和B的cSet可能对相同的C实例有引用。我想序列化A和B,这样在反序列化时就不会有重复的C对象。如果我将Java序列化/反序列化到同一个ObjectOutputStream中,Java会知道如何做正确的事情吗?或者我最终会得到比我开始时更多的C实例吗。这是因为在内部,处理器在“句柄表”中注册所有曾经序列化过的对象。因此,即使多次调用,同一对象也不会被写入两次 API文档用于: (…)使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象的图形恢复为与原始对象写入时相同的形状。(……) 考虑此代码(假设
A
,B
和C
都是,A
和B
有一个指向C
实例的非瞬态字段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
通过调用,您可以清除“句柄表”,使流的行为与新创建的一样
请注意,
ObjectOutputStream
还提供了一种方法,该方法始终将对象作为新的唯一对象写入流。有趣的问题。。。您是否尝试过序列化/反序列化并检查结果?@user1339772,这个问题略有不同,因为它会写入两个不同的文件。就我而言,我仍在给一个文件写信。我希望我会遇到这样的情况,你的问题将对我有很大的参考价值+repI不认为是这种情况,他应该定义一个引用a和B的容器对象,并序列化该容器,当反序列化一切正常时,但调用writeObject(a),writeObject(B)将不能按他所希望的那样工作。@isnot2bad代码应该工作,直到您调用out.reset()
,这清理了那张桌子。@AmirPashazadeh是的,确实如此!请随意复制代码并运行它!
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