14

我正在编写一个基于套接字的小程序。我正在使用类 ModelEvent 通过套接字传递信息。在 ModelEvent 中,有一个类型为 (Object) 的变量对象。

对象本身是具有一些值的二维数组。

object[1][2] = 2;
ModelEvent event = new ModelEvent("allo", object);
dispatchEvent(event);

object[2][3] = 2;
ModelEvent event2 = new ModelEvent("you", object);
dispatchEvent(event2);

假设数组对象填充了值1。第一个事件(event)被客户端接收到,数据是对的。通过数据发送的第二个事件不正确。它的数据与第一次调度中的相同。“allo”和“you”是看我是否没有两次阅读同一个事件,答案不是。字符串是正确的,但对象不是,如果它已更新,则事件。我在发送第二个事件之前遍历数组以查看它是否在服务器端更新,并且确实如此。但是在客户端,即使事件本身发生了变化,它仍然与第一次分派时一样。

4

2 回答 2

27

ObjectOutputStream.reset

重置将忽略已写入流的任何对象的状态。状态被重置为与新的相同ObjectOutputStream。流中的当前点被标记为重置,因此相应ObjectInputStream的点将在同一点重置。之前写入流的对象不会被称为已经在流中。它们将再次写入流。

/* prevent using back references */
output.reset();
output.writeObject(...);

在写入同一个对象之前调用 reset 以确保其更新的状态被序列化。否则,它将仅使用对先前写入的具有过时状态的对象的反向引用。

或者,您也可以ObjectOutputStream.writeUnshared按如下方式使用。

将“未共享”对象写入ObjectOutputStream. 此方法与 相同writeObject,只是它始终将给定对象作为流中的新的唯一对象写入(与指向先前序列化实例的反向引用相反)。

具体来说:

  • 通过 writeUnshared 写入的对象始终以与新出现的对象(尚未写入流的对象)相同的方式序列化,无论该对象之前是否已写入。

  • 如果writeObject用于写入之前已使用 writeUnshared 写入的对象,则将之前的 writeUnshared 操作视为对单独对象的写入。换句话说,ObjectOutputStream永远不会生成对调用写入的对象数据的反向引用writeUnshared

虽然写入对象 viawriteUnshared本身并不能保证在反序列化时对该对象的唯一引用,但它允许在流中多次定义单个对象,这样readUnshared接收方的多次调用就不会发生冲突。请注意,上述规则仅适用于用 编写的基本级别对象writeUnshared,不适用于要序列化的对象图中的任何可传递引用的子对象。

output.writeUnshared(...);

请注意,将此与ObjectInputStream.readUnshared.

ObjectInputStream. 此方法与 readObject 相同,只是它防止后续调用readObjectreadUnshared返回对通过此调用获得的反序列化实例的附加引用。

具体来说:

  • 如果readUnshared调用反序列化反向引用(先前已写入流的对象的流表示),ObjectStreamException将抛出
  • 如果readUnshared成功返回,则任何后续尝试反序列化对反序列化的流句柄的反向引用readUnshared都将导致ObjectStreamException抛出 an 。

通过反序列化对象readUnshared会使与返回的对象关联的流句柄无效。请注意,这本身并不总是保证返回的引用readUnshared是唯一的;反序列化的对象可以定义一个readResolve方法,该方法返回一个对其他方可见的对象,或者 readUnshared 可以返回一个Class对象或常量,该对象或enum常量可在流中的其他地方或通过外部方式获得。如果反序列化的对象定义了一个readResolve方法并且该方法的调用返回一个数组,则readUnshared返回该数组的一个浅克隆;这保证了返回的数组对象是唯一的,并且不能从第二次调用readObject或 readUnshared 获得ObjectInputStream,即使底层数据流已被操纵。

obj = input.readUnshared();
于 2012-09-09T17:20:32.833 回答
4

我没有看到 dispatchEvent 代码,但是根据您所写的内容,我假设如下:您编写了相同的对象(仅更改了其状态),这意味着它将仅写入引用两次。您可以在 java 输出流文档中看到(用于性能)。

您应该使用 writeUnshared(),它将在每次写入时创建一个新对象

我看到有人建议重置,这将使您获得相同的结果,但它会对性能产生影响。

于 2012-09-09T17:22:06.047 回答