Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 通过对象序列化流发送具有不同字段的相同对象_Java_Multithreading_Sockets_Serialization - Fatal编程技术网

Java 通过对象序列化流发送具有不同字段的相同对象

Java 通过对象序列化流发送具有不同字段的相同对象,java,multithreading,sockets,serialization,Java,Multithreading,Sockets,Serialization,我有一个客户机/服务器程序,我通过ObjectOutputStream通过writeObject()和readObject()发送对象 我要发送的对象是一个类,由两个字段和内部的另一个对象组成(让我们调用外部对象包装器和内部对象内部。这两个自定义对象都实现了可序列化 我第一次发送包装时,一切工作都完美无缺。存储在包装、内部和所有字段中的所有内容都可以毫无问题地序列化和反序列化 但是,当客户端修改内部类,将其放入包装器,并再次发送时,服务器接收到的内部实例与第一次接收到的实例相同 我的客户: i

我有一个客户机/服务器程序,我通过
ObjectOutputStream
通过
writeObject()
readObject()
发送对象

我要发送的对象是一个类,由两个字段和内部的另一个对象组成(让我们调用外部对象
包装器
和内部对象
内部
。这两个自定义对象都实现了
可序列化

我第一次发送
包装
时,一切工作都完美无缺。存储在
包装
内部
和所有字段中的所有内容都可以毫无问题地序列化和反序列化

但是,当客户端修改
内部
类,将其放入
包装器
,并再次发送时,服务器接收到的
内部
实例与第一次接收到的实例相同

我的客户:

internal=新内部();
内部设置值(“值”);
ObjectOutputStream out=新的ObjectOutputStream(socket.getOutputStream());
writeObject(新包装器(内部));
服务器:

ObjectInputStream in=new ObjectInputStream(clientSocket.getInputStream());
Wrapper=.readObject()中的(Wrapper);
字符串值=wrapper.getInner().getValue();
然后,客户机使用不同的字符串(即,包含其他字母,然后是第一个字母)修改
内部
类(与以前相同的实例):

internal.setValue(“newValue”);
writeObject(新包装器(内部));
但是,当我查看服务器上的
内部.getValue()
时,它没有改变,仍然等于
的“value”

我通过制作内部类的硬拷贝解决了这个问题,然后将其发送过来:

Inner newInner=newInner();
newInner.setValue(“newValue”);
writeObject(新包装器(新内部));
现在,新值将按其应该的方式更新


为什么序列化会以这种方式工作?

这是的预期行为。引用Javadocs:

使用引用共享机制对单个对象的多个引用进行编码,以便可以将对象的图形恢复为与原始对象写入时相同的形状

由于您使用的是同一个内部类引用,因此它只发送一个对以前发送的对象的引用。它不会检查所有对象的所有字段以查看是否有任何字段发生了更改。我怀疑不仅仅是was
internal.getValue()
等于发送的第一个对象,但服务器在第二个对象中接收到的
内部
对象与第一个对象的
内部
对象是相同的对象(
=

如果你打过电话:

out.reset();

在发送带有调整后的
内部
字段的对象之前,您的代码应该可以工作。
reset()
方法清除引用缓存,这有助于提高序列化流的效率。
reset()
如果您要跨流发送大量临时对象,这一点尤其必要,因为否则这些对象会缓存在内存中,并可能导致堆耗尽。

这很有效。非常感谢。如果允许,我会将其标记为答案。另外,感谢您编辑标题。我真的不知道该放什么。App谢谢!