为什么写回两个不同Streams的单个对象在回读时代表两个不同的对象?

时间:2011-11-15 18:12:12

标签: java serialization

标题告诉我需要,以下是我正在使用的代码:

测试用例

SameObjectDifferentStreams same = new SameObjectDifferentStreams(); 
ObjectOutputStream out1 = new ObjectOutputStream(new FileOutputStream("file1"));
ObjectOutputStream out2 = new ObjectOutputStream(new FileOutputStream("file2"));

out1.writeObject(same);
out1.close();

out2.writeObject(same);
out2.close();

System.out.println("The Original reference is :" + same.toString());

oin1 = new ObjectInputStream(new FileInputStream("file1"));
oin2 = new ObjectInputStream(new FileInputStream("file2"));

SameObjectDifferentStreams same1 = 
    (SameObjectDifferentStreams) oin1.readObject();
System.out.println("The First Instance is :" + same1.toString());

SameObjectDifferentStreams same2 = 
    (SameObjectDifferentStreams) oin2.readObject();
System.out.println("The Second Instance is :" + same2.toString());

输出

The Original reference is :serialization.SameObjectDifferentStreams@9304b1
The First Instance is :serialization.SameObjectDifferentStreams@190d11
The Second Instance is :serialization.SameObjectDifferentStreams@a90653

4 个答案:

答案 0 :(得分:6)

当您将对象写入流时,实际上序列化它,即仅写入其数据。然后,当您阅读它时,您将读取数据并创建新对象。就像你用适当的构造函数参数调用new MyObject()一样。显然,这里创建了新对象。

如果两次读取相同的序列化对象,则创建两次新实例。这两个实例是相等的,即它们的所有字段都相等,但引用不同,因此表达式o1==o2返回false,而(如果实现合理的equals()方法)o1.equals(o2)返回true。

答案 1 :(得分:4)

这个问题在分布式计算中称为EQ,有些系统会尝试解决它,但Java反序列化却没有。

想象一下,两个不同的流在两个不同的Java虚拟机中处于两个不同的进程中。两个不同的读取必须导致两个不同的对象,因为流实现无法实现此文件中的这些字节对应于已在内存中但已在另一个进程中的此对象。

当两个流在同一个虚拟机中时存在同样的问题 - 从内存中的字节到对象的映射是不可指定的,因为Java序列化不会为对象分配全局唯一的地址,即使它确实存在,如果没有包含每个序列化/反序列化对象的键入口的对象的全局弱映射,即使在单个存储桶中也无法强制执行唯一性。 Java序列化只是为了在不同的反序列化会话之间保留对象标识。

答案 2 :(得分:4)

如果它们不是两个不同的对象,那么使用这些对象是不可能的。考虑物理世界中的类比:我写了一封信并邮寄给你。你开始阅读它。然后我开始更改信件发送给其他人,你的信件的副本开始改变!

答案 3 :(得分:2)

它们是不同的,因为当你写一个对象时,你会写一个该对象的副本。当您将其读回时,该副本将放置在内存中分配的新对象中。如果比较same1和same2,它们将是内存中的不同对象。

我怀疑你正在做某个比较,比如

same1 == same2

并返回false。它们是记忆中的不同对象。尝试覆盖equals方法并比较一些字段是否相等。