问题
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,
ObjectOutputStreamfirst looks to see if the methodwriteObject( ObjectOutputStream oos)exists. If it does, then it calls that method with itself as an argument. ThewriteObjectmethod then dispatches the call back to theObjectOutputStream(thus making this a double dispatch). In making this very simple call back,ObjectOutputStreamhas said: "I'm delegating back to you the responsibility of writing your state onto this stream". In making that simple choice,ObjectOutputStreamhas decoupled itself from our objectA. ObjectAin 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:
- "
ObjectOutputStreamfirst looks to see if the methodwriteObject( ObjectOutputStream oos)exists". Why wouldObjectOutputStreamneed 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
writeObjectwith an instance ofAas an argument. Going back to the previous item, why would it look for thewriteObjectsignature with anObjectOutputStreamarg if it's being called with an instance ofA? - "The
writeObjectmethod then dispatches the call back to theObjectOutputStream(thus making this a double dispatch)". Again, thewriteObjectmethod belongs to theObjectOutputStreamclass 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.
回答1:
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
ObjectOutputStreamcalls 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 theObjectOutputStreamto write elements of itself. It is not supposed to calloos.writeObject(this)again.
For example, suppose I had an object like this:
class A {
int x;
}
If I wanted to enable it to write itself to an ObjectOutputStream, I might expand it like this:
class A implements Serializable {
int x;
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.writeInt(x);
}
}
Then this code:
A a = new A();
ObjectOutputStream oos = . . .;
oos.writeObject(a);
would use the writeObject method in class A to write a, rather than using reflection to write all the (non-transient) fields of A. (In this case, however, there would be no difference.)
回答2:
From the documentation of the Serializable interface:
Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures:
private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void readObjectNoData() throws ObjectStreamException;
If you want to make your class serializable implementing the interface is enough. But, if you want make the object (of the class) itself tell the output stream how to serialize it's own state then it should implement those methods.
来源:https://stackoverflow.com/questions/13151524/double-dispatch-in-java-example