Java 为什么在序列化/反序列化的情况下只创建一个父对象
为什么在序列化/反序列化的情况下只创建一个父对象Java 为什么在序列化/反序列化的情况下只创建一个父对象,java,serialization,deserialization,Java,Serialization,Deserialization,为什么在序列化/反序列化的情况下只创建一个父对象 //superclass A //A class doesn't implement Serializable //interface. class A { int i; // parameterized constructor public A(int i) { this.i = i; } // default constructor public A()
//superclass A
//A class doesn't implement Serializable
//interface.
class A
{
int i;
// parameterized constructor
public A(int i)
{
this.i = i;
}
// default constructor
public A()
{
i = 50;
System.out.println("A's class constructor called");
}
}
// subclass B implementing Serializable interface
class B extends A implements Serializable
{
int j;
public B(int i, int j)
{
super(i);
System.out.println("B.B()");
this.j = j;
}
}
// Driver class
public class SerializationWithInheritanceExample
{
public static void main(String[] args) throws Exception
{
B b1 = new B(10, 20);
System.out.println("i = " + b1.i);
System.out.println("j = " + b1.j);
// Serializing B's(subclass) object
try (FileOutputStream fos = new FileOutputStream("abc.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos))
{
// Method for serialization of B's class object
oos.writeObject(b1);
}
System.out.println("Object has been serialized\n");
// Reading the object from a file
readObject();
readObject();
readObject();
}
static void readObject()
{
// Reading the object from a file
try (FileInputStream fis = new FileInputStream("abc.ser"); ObjectInputStream ois = new ObjectInputStream(fis))
{
// Method for de-serialization of B's class object
B b2 = (B) ois.readObject();
System.out.println("HasCode of A:"+ b2.getClass().getSuperclass().hashCode() +" | HasCode of B:"+b2.hashCode());
System.out.println("i = " + b2.i);
System.out.println("j = " + b2.j);
} catch (IOException | ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
输出
B.B()
i = 10
j = 20
Object has been serialized
A's class constructor called
HasCode of A:1311053135 | HasCode of B:1705736037
i = 50
j = 20
A's class constructor called
HasCode of A:1311053135 | HasCode of B:455659002
i = 50
j = 20
A's class constructor called
HasCode of A:1311053135 | HasCode of B:250421012
i = 50
j = 20
在多次反序列化B的对象时,只创建一个A类父对象。
为什么只创建一个对象?您不是在调用
A
实例的hashCode()
方法,而是在类A
中,在大多数情况下,类对象只有一个实例
让我们把它分解一下:
b2 // instance of B
.getClass() // Class<B>
.getSuperclass() // Class<A>
.hashCode() // hash code of Class<A>
b2//B的实例
.getClass()//类
.getSuperclass()//类
.hashCode()//类的哈希代码
甚至不可能为B
实例的“部分a
”获取单独的哈希代码:只有一个对象,它只有一个哈希代码
当你创建一个
B
时,只会创建一个对象,而不是像你想象的那样创建两个。此对象包含所有B
,其中包括A
的部分。在A的情况下,您得到A类的hashcodeA。在B的情况下,您得到实例的hashcodeB。并且您的3个B实例共享1个超类A(与类B一起)。因此,例如,如果您调用b2.getClass().hashcode()
三次,那么所有这些方法调用的输出也将相等,因为您有一个类B。当您调用b2.getClass().getSuperclass()
时,您有一个类型为class
的实例。这是类A的唯一对象,它包含有关类A
声明的信息。当您调用b2.hashCode()
时,您有实例的哈希代码,它引用了b2
为什么说“只创建了一个A类父对象”是因为A的哈希代码被打印出来了吗?如果是,请重新检查代码。。这是类的哈希代码,而不是对象的哈希代码。JVM只会将一个对象类的一个实例加载到每个类加载器的内存中。您应该使用B的哈希代码作为每次加载A的证据。感谢@ChrisK的解释。“只创建了一个A类父对象”显然是错误的。这些痕迹表明创建了三个。您的问题没有意义。@EJP Yes我的理解是错误的。这个答案可以通过解释为什么只为B创建一个对象来改进。下面的链接解释了相互扩展的对象的JVM内存布局。关键在于,在内存中,B由B和A在单个内存序列中的串联表示。