I was reading the Wikipedia article on DD and jumped over to the "Double dispatch in Java and an example" link given at the end. The description of the following Serializable example seems rather confusing to me:
A a = new A();
ObjectOutputStream oos = new ObjectOutputStream();
oos.writeObject( a);
Here's the description:
In order to serialize A,
ObjectOutputStream
first looks to see if the methodwriteObject( ObjectOutputStream oos)
exists. If it does, then it calls that method with itself as an argument. ThewriteObject
method then dispatches the call back to theObjectOutputStream
(thus making this a double dispatch). In making this very simple call back,ObjectOutputStream
has said: "I'm delegating back to you the responsibility of writing your state onto this stream". In making that simple choice,ObjectOutputStream
has decoupled itself from our objectA
. ObjectA
in turn says ok, here is some state that I want written on the stream. If the value is a primitive, then it can be dealt by the overloading of the write method. If not, the back and forth can continue at the next level down in the objects graph until all of the useful state has been placed on the stream.
I'm guessing that the description might be confusing because what is being described is what is happening behind the scenes and not the code presented because otherwise it doesn't seem to make much sense. Here are the parts that confuse me:
- "
ObjectOutputStream
first looks to see if the methodwriteObject( ObjectOutputStream oos)
exists". Why wouldObjectOutputStream
need to check for the existence of this method since it is its own method? - "If it does, then it calls that method with itself as an argument". It looks to me like it's calling
writeObject
with an instance ofA
as an argument. Going back to the previous item, why would it look for thewriteObject
signature with anObjectOutputStream
arg if it's being called with an instance ofA
? - "The
writeObject
method then dispatches the call back to theObjectOutputStream
(thus making this a double dispatch)". Again, thewriteObject
method belongs to theObjectOutputStream
class so I fail to see how this gets "dispatched back to theObjectOutputStream
" since that appears to be the original destination.
Am I just missing something fundamental here or is this a poorly written/described example? If it is a bad example, I'd like to change the Wikipedia article to point to a better one so feel free to provide suggestions.
Thanks.
To answer your questions in order:
ObjectOutputStream.writeObject(Object)
checks its argument (using reflection) to determine if the object implementswriteObject(ObjectOutputStream)
. That is, it more or less asks the object, "Do you know how to write your structure to anObjectOutputStream
?"If the answer is "yes", then the
ObjectOutputStream
calls the object'swriteObject(ObjectOutputStream)
method, passing itself (theObjectOutputStream
, not the object) as the argument. It basically says, "Good. Write your structure to me."The implementation of
writeObject(ObjectOutputStream)
in the object calls on theObjectOutputStream
to write elements of itself. It is not supposed to calloos.writeObject(this)
again.For example, suppose I had an object like this:
If I wanted to enable it to write itself to an
ObjectOutputStream
, I might expand it like this:Then this code:
would use the
writeObject
method in classA
to writea
, rather than using reflection to write all the (non-transient) fields of A. (In this case, however, there would be no difference.)