2

我正在阅读关于DD的 Wikipedia 文章,然后跳到最后给出的“Java 中的双重调度和示例”链接。以下 Serializable 示例的描述对我来说似乎相当混乱:

A a = new A();
ObjectOutputStream oos = new ObjectOutputStream();
oos.writeObject( a);

这是描述:

为了序列化A,ObjectOutputStream首先查看该方法是否writeObject( ObjectOutputStream oos)存在。如果是这样,那么它以自身作为参数调用该方法。然后该writeObject方法将调用分派回ObjectOutputStream(从而使其成为双重分派)。在进行这个非常简单的回调时,ObjectOutputStream他说:“我将把你的状态写入这个流的责任委托给你”。在做出这个简单的选择时,ObjectOutputStream它已经从我们的对象中解耦了A。对象A反过来说好的,这是我想写在流上的一些状态。如果该值是一个原始值,那么它可以通过 write 方法的重载来处理。如果没有,则可以在对象图中的下一个级别继续来回,直到所有有用的状态都已放置在流上。

我猜测描述可能会令人困惑,因为所描述的是幕后发生的事情,而不是呈现的代码,否则它似乎没有多大意义。以下是让我感到困惑的部分:

  • ObjectOutputStream首先查看该方法是否writeObject( ObjectOutputStream oos)存在”。为什么ObjectOutputStream需要检查这个方法是否存在,因为它是它自己的方法?
  • “如果是这样,那么它会以自身作为参数调用该方法”。在我看来,它writeObject使用实例A作为参数调用。回到上一项,如果它是用 的实例调用的,为什么还要寻找writeObject带有 arg 的签名?ObjectOutputStreamA
  • writeObject然后该方法将调用分派回ObjectOutputStream(从而使其成为双重分派)”。同样,该writeObject方法属于ObjectOutputStream该类,因此我看不到它是如何“派回的ObjectOutputStream”,因为那似乎是原始目的地。

我只是在这里遗漏了一些基本的东西,还是这是一个写得不好/描述得不好的例子?如果这是一个不好的例子,我想更改 Wikipedia 文章以指向更好的文章,因此请随时提供建议。

谢谢。

4

2 回答 2

4

按顺序回答您的问题:

  1. ObjectOutputStream.writeObject(Object)检查其参数(使用反射)以确定对象是否实现writeObject(ObjectOutputStream). 也就是说,它或多或少地问对象,“你知道如何将你的结构写到一个? 中ObjectOutputStream?”

  2. 如果答案是“是”,则ObjectOutputStream调用对象的 writeObject(ObjectOutputStream)方法,将自身(ObjectOutputStream不是对象)作为参数传递。它基本上说,“好。把你的结构写给我。”

  3. 对象中的实现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 的所有(非瞬态)字段。(但是,在这种情况下,没有区别。)

于 2012-10-31T05:08:18.150 回答
1

Serializable接口的文档中:

在序列化和反序列化过程中需要特殊处理的类必须实现具有这些确切签名的特殊方法:

private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException; private void readObjectNoData() 抛出 ObjectStreamException;

如果你想让你的类可序列化,实现接口就足够了。但是,如果你想让(类的)对象本身告诉输出流如何序列化它自己的状态,那么它应该实现这些方法。

于 2012-10-31T05:14:54.603 回答