Java serialization and duplicate objects
duplicates, java, serialization
Solution
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!
API documentation for `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. (...)
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
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.
Note that a `ObjectOutputStream` also offers a method `writeObjectUnshared(Object)` that always writes an object as a new unique object to the stream.
Problem
I have the following setup: ``` public class A { private Set<C> cSet; } public class B { private Set<C> cSet; } public class 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?