2012-09-09 10 views
11

我在写一个基于socket的小程序。我正在使用类ModelEvent通过套接字传递信息。在ModelEvent中,有一个类型为(Object)的变量obect。Java套接字/序列化,对象不会更新

对象本身是一个具有一些值的2D数组。

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,客户端收到第一个事件(事件),数据正确。通过数据发送的第二个事件是不正确的。其数据与第一次派发相同。 “allo”和“you”是看我是不是两次阅读同一个事件,而不是这个答案。该字符串是正确的,但该对象不是,如果它已被更新,则为事件。我在发送第二个事件之前遍历数组,以查看它是否在服务器端更新,它是。但是在客户端,即使事件本身发生了变化,它仍然与第一次调度相同。

+0

你是如何在客户端阅读的? –

+0

ObjectInputStream.readObject和我投它 – maniak

回答

20

请参阅ObjectOutputStream.reset

重置将忽略已写入流的任何对象的状态。状态重置为与新的ObjectOutputStream相同。流中的当前点标记为重置,因此相应的ObjectInputStream将在同一点重置。以前写入流的对象不会被认为已经在流中。他们会再次被写入流中。写同一个对象,以确保其更新的状态是序列化之前

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

呼叫复位。否则,它将仅使用反向参考来处理先前写入的过时状态的对象。

或者,您可以选择使用ObjectOutputStream.writeUnshared,如下所示。

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

具体来说:

  • 经由与writeUnshared写入的对象总是以相同的方式作为一个新出现的对象(即还没有被写入流又一个对象)序列,而不管是否对象先前已被写入。

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

虽然本身经由writeUnshared写入对象并不保证一个唯一的参考对象时其反序列化,它允许一个单一的对象到流中的被定义多次,所以通过多次调用readUnshared接收器不会发生冲突。请注意,上述规则仅适用于使用writeUnshared编写的基本级别对象,而不适用于要序列化的对象图中任何传递引用的子对象。

output.writeUnshared(...); 

注意这是很好的做法,还有一点,ObjectInputStream.readUnshared

ObjectInputStream中读取“未共享”对象。此方法与readObject相同,只是它阻止后续调用readObjectreadUnshared将附加引用返回到通过此调用获取的反序列化实例。

具体来说:

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

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

obj = input.readUnshared(); 
+1

我想亲吻你吧! *没有同性恋者*谢谢。为了理解,当一个对象被发送两次到流时,它会记住它以前的状态并使用旧的状态? – maniak

+0

是的,它:)!我认为这是出于表演的原因,但它不适合你想要的用途。 – Flawyte

3

我没有看到dispatchEvent代码,而是从你写的东西我假定: 你写的同一对象(仅其状态更改),这意味着它将只写了两次参考。您可以在java输出流文档中看到(用于性能)。

你应该使用与writeUnshared(),这将创建一个新的对象上的每个写

我看到复位建议,这将让你同样的结果,但它的性能影响。

+0

+1指出性能影响。我在修改我的答案,在发布时加入'writeUnshared'。 – oldrinb

+1

-1表示'性能影响'。 writeUnshared()和reset()/ writeObject()之间的唯一区别在于,在第一种情况下,被引用的对象仍然可以作为句柄被发送。这是一个主要的*功能*差异,它可能不是OP想要的。将所有这些仅仅归结为“性能影响”是完全不正确的,完全是误导性的。 – EJP