[英]Sending the same objects with different fields over an object serialized stream
我有一個客戶端/服務器程序,我通過writeObject()
和readObject()
通過ObjectOutputStream
發送對象。
我發送的對象是由幾個字段組成的類,另一個是內部對象(讓我們調用外部對象Wrapper
和內部Inner
。兩個自定義對象都實現了可serializable
。
我第一次發送Wrapper
,一切都完美無瑕。 存儲在Wrapper
, Inner
和所有字段中的所有內容都會Wrapper
化和反序列化而不會出現問題。
但是,當客戶端然后修改Inner
類時,將其放入Wrapper
,並再次發送它,服務器接收的Inner
實例與第一次接收的實例相同。
我的客戶:
Inner inner = new Inner();
inner.setValue("value");
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(new Wrapper(inner));
服務器:
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
Wrapper wrapper = (Wrapper) in.readObject();
String value = wrapper.getInner().getValue();
然后,客戶端使用不同的字符串(即包含其他字母,然后是第一個字符串)修改Inner
類(與之前相同的實例):
inner.setValue("newValue");
out.writeObject(new Wrapper(inner));
但是,當我查看服務器上的inner.getValue()
時,它沒有更改,仍然等於"value"
。
我通過制作內部類的硬拷貝,然后發送它來解決這個問題:
Inner newInner = new Inner();
newInner.setValue("newValue");
out.writeObject(new Wrapper(newInner));
現在,新值將按預期更新。
為什么序列化以這種方式工作?
這是ObjectOutputStream
的預期行為。 引用Javadocs:
使用引用共享機制對對單個對象的多個引用進行編碼,以便可以將對象圖形恢復為與寫入原始圖像時相同的形狀。
由於您使用相同的內部類引用,它只是通過對先前發送的對象的引用發送。 它不檢查所有的所有對象的字段,看其中是否已經改變。 我懷疑不僅是inner.getValue()
等於所發送的第一對象,但該inner
的第二對象由服務器接收的對象是相同的對象 ( ==
)作為inner
從所述第一對象。
如果你打電話:
out.reset();
在使用調整后的inner
字段發送對象之前,您的代碼應該可以正常工作。 reset()
方法清除引用緩存,這有助於序列化流的高效。 作為旁注,如果要在流中發送大量臨時對象,則reset()
尤其必要,因為否則這些對象會緩存在內存中並導致堆耗盡。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.