我正在阅读DD上的维基百科文章,并跳到最后给出的"Double dispatch in Java and an example"链接。以下Serializable示例的描述对我来说似乎相当混乱:
A a = new A();
ObjectOutputStream oos = new ObjectOutputStream();
oos.writeObject( a);
以下是描述:
为了序列化A,
ObjectOutputStream
首先查看方法writeObject( ObjectOutputStream oos)
是否存在。如果是,则调用该方法作为参数。然后writeObject
方法将调用发送回ObjectOutputStream
(从而使其成为双重调度)。在进行这个非常简单的回调时,ObjectOutputStream
已经说过:“我将你的州写入这个流的责任归还给你”。在做出这个简单的选择时,ObjectOutputStream
已将自己与对象A
分离。对象A
反过来说好了,这是我想在流上写的一些状态。如果该值是基元,则可以通过写入方法的重载来处理它。如果没有,则来回可以在对象图中的下一级继续,直到所有有用的状态都被放置在流上。
我猜测描述可能会令人困惑,因为所描述的是幕后发生的事情,而不是代码,因为否则它似乎没有多大意义。以下是令我困惑的部分:
ObjectOutputStream
首先查看方法writeObject( ObjectOutputStream oos)
是否存在”。为什么ObjectOutputStream
需要检查此方法是否存在,因为它是自己的方法?writeObject
的实例作为参数调用A
。回到上一个项目,如果使用writeObject
的实例调用ObjectOutputStream
arg,为什么它会查找带有A
arg的writeObject
签名?ObjectOutputStream
方法然后将回调调度回writeObject
(从而使其成为双重调度)”。同样,ObjectOutputStream
方法属于ObjectOutputStream
类,因此我无法看到它如何“发送回{{1}}”,因为它似乎是原始目标。我是否只是缺少一些基本的东西,或者这是一个写得不好的/描述的例子?如果这是一个不好的例子,我想改变维基百科的文章,指出一个更好的文章,所以随时提供建议。
感谢。
答案 0 :(得分:4)
按顺序回答您的问题:
ObjectOutputStream.writeObject(Object)
检查其参数(使用反射)以确定对象是否实现writeObject(ObjectOutputStream)
。也就是说,它或多或少地询问对象,“你知道如何将你的结构写成ObjectOutputStream
吗?”
如果答案为“是”,则ObjectOutputStream
调用对象的 writeObject(ObjectOutputStream)
方法,传递自己(ObjectOutputStream
,而不是object)作为参数。它基本上说:“好。把你的结构写给我。”
对象中writeObject(ObjectOutputStream)
的实现调用ObjectOutputStream
来编写自身的元素。它不应该再次呼叫oos.writeObject(this)
。
例如,假设我有一个这样的对象:
class A {
int x;
}
如果我想让它自己写入ObjectOutputStream
,我可能会像这样展开它:
class A implements Serializable {
int x;
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.writeInt(x);
}
}
然后这段代码:
A a = new A();
ObjectOutputStream oos = . . .;
oos.writeObject(a);
会使用类writeObject
中的A
方法来编写a
,而不是使用反射来编写A的所有(非瞬态)字段。(在这种情况下,不过,没有区别。)
答案 1 :(得分:1)
来自Serializable
界面的文档:
在序列化期间需要特殊处理的类 反序列化过程必须实现这些特殊方法 确切的签名:
private void writeObject(java.io.ObjectOutputStream out) 抛出IOException private void readObject(java.io.ObjectInputStream in) 抛出IOException,ClassNotFoundException; private void readObjectNoData() 抛出ObjectStreamException;
如果你想使你的类可序列化实现接口就足够了。但是,如果你想让make(类的)对象本身告诉输出流如何序列化它自己的状态,那么它应该实现这些方法。