2012-09-09 11 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