反序列化对象是否与原始对象的实例相同
2022-09-02 03:48:04
当我从类中实例化对象时,一个对象保存在java堆中。当我通过序列化对象来保存对象,然后反序列化对象时,我是否正确地理解该对象现在将具有新的堆地址,但仍将是该类的完全相同的实例。
当我从类中实例化对象时,一个对象保存在java堆中。当我通过序列化对象来保存对象,然后反序列化对象时,我是否正确地理解该对象现在将具有新的堆地址,但仍将是该类的完全相同的实例。
您的问题的答案不能只是“是”或“否”。分析概念是必需的。我会建议你拿一支铅笔和纸,自己做,记住以下几点。
请看下图,在您的上下文中描绘上述概念:
所有对象 A 引用都指向一个堆条目,如果您尝试 objectB.getObjectA() == objectC.getObjectA() 或任何其他此类操作,您将获得 true。
案例1当您单独保存对象并反序列化它们时,堆中会发生什么情况:
正如你现在所发现的,objectBcopy.getObjectA() == objectCcopy.getObjectA() 不会返回 true,因为对象 A 对复制对象的引用不再相同。
案例 2相反,当您将对象保存在单个文件中并在以后反序列化它们时,以下是堆中发生的情况:
正如你现在所知道的,objectBcopy.getObjectA() == objectCcopy.getObjectA() 现在将是正确的,因为对象 A 副本的引用是相同的,但这仍然是对象 A 的新副本。
支持我的扣除的快速程序(案例1和案例2):
public class Test{
public static void main (String args[]) throws IOException, ClassNotFoundException{
A a = new A();
B b = new B();
b.a = a;
C c = new C();
c.a = a;
System.out.println("b.a == c.a is " + (b.a == c.a));
// Case 1 - when two diferent files are used to write the objects
FileOutputStream fout = new FileOutputStream("c:\\b.ser");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(b);
oos.close();
fout.close();
fout = new FileOutputStream("c:\\c.ser");
oos = new ObjectOutputStream(fout);
oos.writeObject(c);
oos.close();
fout.close();
FileInputStream fileIn = new FileInputStream("c:\\b.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
B bCopy = (B) in.readObject();
in.close();
fileIn.close();
fileIn = new FileInputStream("c:\\c.ser");
in = new ObjectInputStream(fileIn);
C cCopy = (C) in.readObject();
in.close();
fileIn.close();
System.out.println("Case 1 - bCopy.a == cCopy.a is " + (bCopy.a == cCopy.a));
// Case 2 - when both the objects are saved in the same file
fout = new FileOutputStream("c:\\both.ser");
oos = new ObjectOutputStream(fout);
oos.writeObject(b);
oos.writeObject(c);
oos.close();
fout.close();
fileIn = new FileInputStream("c:\\both.ser");
in = new ObjectInputStream(fileIn);
bCopy = (B) in.readObject();
cCopy = (C) in.readObject();
in.close();
fileIn.close();
System.out.println("Case 2 - bCopy.a == cCopy.a is " + (bCopy.a == cCopy.a));
}
}
class A implements Serializable{
}
class B implements Serializable{
A a;
}
class C implements Serializable{
A a;
}
具有以下输出:
b.a == c.a is true
Case 1 - bCopy.a == cCopy.a is false
Case 2 - bCopy.a == cCopy.a is true
序列化之前:
A originalA = ...;
B.a == C.a == D.a == E.a == originalA
所有 、 和 都指向 、 的同一引用。B.a
C.a
D.a
E.a
A
originalA
序列化和反序列化之后:
A otherA = ...;
B.a == C.a == D.a == E.a == otherA
所有 、 和 都指向 、 的同一引用。B.a
C.a
D.a
E.a
A
otherA
然而:
originalA != otherA
虽然
originalA.equals(otherA) == true
注意:仅当它被覆盖以基于序列化字段一致地检查相等性时才会返回。否则,它可能会返回 。equals()
true
false
编辑:
证明:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Sample {
static class A implements Serializable {
private static final long serialVersionUID = 1L;
}
static class B implements Serializable {
private static final long serialVersionUID = 1L;
A a;
}
static class C implements Serializable {
private static final long serialVersionUID = 1L;
A a;
}
public static void main(String args[]) throws IOException, ClassNotFoundException {
A originalA = new A();
B b = new B();
b.a = originalA;
C c = new C();
c.a = originalA;
System.out.println("b.a == c.a is " + (b.a == c.a));
FileOutputStream fout = new FileOutputStream("ser");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(b);
oos.writeObject(c);
oos.close();
fout.close();
FileInputStream fileIn = new FileInputStream("ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
B bDeserialized = (B) in.readObject();
C cDeserialized = (C) in.readObject();
in.close();
fileIn.close();
System.out.println("bDeserialized.a == cDeserialized.a is " + (bDeserialized.a == cDeserialized.a));
}
}