Java套接字/序列化,对象不会更新

时间:2012-09-09 17:07:26

标签: java sockets serialization

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

对象本身是一个带有一些值的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”是为了看我是不是两次读同一个事件而答案不是。字符串是正确的,但对象不是,如果已更新,则为event。我在发送第二个事件之前迭代数组,以查看它是否在服务器端更新,它是。但在客户端,它仍然与第一次发送时相同,即使事件本身已更改。

2 个答案:

答案 0 :(得分:23)

请参阅ObjectOutputStream.reset

  

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

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

在写入同一对象之前调用reset,以确保其序列化更新状态。否则,它只会将后引用用于之前写入的对象及其过时状态。

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

  

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

     

具体做法是:

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

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

  •   
     

虽然通过writeUnshared编写对象本身并不保证对象在反序列化时对该对象的唯一引用,但它允许在流中多次定义单个对象,以便多次调用{{ 1}}由接收者不会发生冲突。请注意,上述规则仅适用于使用readUnshared编写的基础级对象,而不适用于要序列化的对象图中的任何可传递引用的子对象。

writeUnshared

请注意,最好将此与ObjectInputStream.readUnshared结合使用。

  

output.writeUnshared(...); 读取“非共享”对象。此方法与readObject相同,不同之处在于它阻止对ObjectInputStreamreadObject的后续调用返回对通过此调用获得的反序列化实例的其他引用。

     

具体做法是:

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

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

ObjectInputStream

答案 1 :(得分:3)

我没有看到dispatchEvent代码,但是从你写的内容我假设如下: 你写同一个对象(只改变它的状态),这意味着它只会写两次引用。你可以在java输出流文档中看到(性能)。

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

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