13

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?

4
  • 3
    Interesting question... have you tried serializing/deserializing and check the results? Commented Nov 19, 2013 at 16:27
  • stackoverflow.com/questions/2665567/… Commented Nov 19, 2013 at 16:29
  • @user1339772, that question is slightly different in that it writes to two different files. In my case I am still writing to one file. Commented Nov 19, 2013 at 16:33
  • I hope I am going to run into such a case, and your question will be great reference to me. +rep Commented Nov 19, 2013 at 17:06

1 Answer 1

16

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.

Sign up to request clarification or add additional context in comments.

3 Comments

I don't think that's the case, he should define a container object referencing to both A and B, and serialize that container, when deserializing everything goes fine, but calling writeObject(a), writeObject(b) shall not work as he wants.
@isnot2bad code should work until you call out.reset(), which clears that handling table.
@AmirPashazadeh yes indeed, its exactly like that! Feel free to copy the code and run it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.