[英]If the serialization is inherited in a hierarchy then the constructor of class not implementing serializable will be called. Why is this so?
Why is constructor of the Food and Fruit class called when I deserialize where as the constructor of SkinFruit and Banana2 is not called in the below example? 当我反序列化以下示例中的SkinFruit和Banana2的构造函数时,为什么要调用Food and Fruit类的构造函数?
Suppose I have following class hierarchy 假设我有以下课程层次结构
class Food{
public Food() { System.out.println("1"); }
}
class Fruit extends Food {
public Fruit() { System.out.print("2"); }
}
class SkinFruit extends Fruit implements Serializable{
SkinFruit() { System.out.print("3"); }
}
public class Banana2 extends SkinFruit {
private static final long serialVersionUID = 1L;
int size = 42;
public static void main(String [] args) {
Banana2 b = new Banana2();
FileOutputStream fost;
try {
fost = new FileOutputStream(new File("d:/testbanana.ser"));
ObjectOutputStream oostr= new ObjectOutputStream(fost);
oostr.writeObject(b);
oostr.flush();
oostr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fin= new FileInputStream(new File("d:/testbanana.ser"));
ObjectInputStream objin= new ObjectInputStream(fin);
b=(Banana2)objin.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(" restored "+ b.size + "" );
}
}
Because that's how (de)serialization works. 因为这就是反序列化的工作方式。 It is a separate mechanism from regular object construction.
它是与常规对象构造不同的机制。
If the constructor of Class A is called, that's because Class A itself does not implement Serializable
. 如果调用了Class A的构造函数,那是因为Class A本身未实现
Serializable
。 During Deserialization, the parameterless constructor of the first non-serializable class in the inheritance hierarchy is called (possibly that of java.lang.Object
). 反序列化期间,将调用继承层次结构中第一个不可序列化类的无参数构造函数(可能是
java.lang.Object
无参数构造函数)。 If that class does not have a parameterless constructor, there will be an Exception. 如果该类没有无参数的构造函数,则将发生异常。
Neither is called, because your class is not Serializable. 两者都不被调用,因为您的类不可序列化。
You cannot call the B()
without calling A()
because B calls A. 您不能不调用
B()
就调用A()
因为B调用了A。
Consider the following program 考虑以下程序
public static void main(String... args) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(new B());
oos.writeObject(new D());
oos.close();
System.out.println("-------------");
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
System.out.println("deserialize B");
ois.readObject();
System.out.println("deserialize D");
ois.readObject();
}
static class A {
public A() {
System.out.println("Inside class A");
}
}
static class B extends A implements Serializable {
public B() {
System.out.println("Inside class B");
}
}
static class C implements Serializable {
public C() {
System.out.println("Inside class C");
}
}
static class D extends C {
public D() {
System.out.println("Inside class D");
}
}
prints 版画
Inside class A
Inside class B
Inside class C
Inside class D
-------------
deserialize B
Inside class A
deserialize D
A is the non Serializable parent of B. It is not Serialized and so the constructor has to be called to set any fields which need to be set. A是B的不可序列化的父级。它没有被序列化,因此必须调用构造函数以设置需要设置的任何字段。 However, B, C and D are all Serializable and their fields have been serializable and will be reset.
但是,B,C和D都是可序列化的,并且它们的字段已被序列化并将被重置。 There is no need to call the constructor.
无需调用构造函数。
If at all you want to re-create some information when the object is being deserialized, you should use the below method implementation inside your Serializable
class. 如果您要在反序列化对象时完全重新创建一些信息,则应在
Serializable
类中使用以下方法实现。 For instance, put the below code inside B
. 例如,将下面的代码放入
B
。
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("Resurrecting B");
}
The other one is for serialization, just in case you want to do some stuff before the object gets written off. 另一个用于序列化,以防万一您想在对象被注销之前做一些事情。
private void writeObject(ObjectOutputStream out) throws IOException {
// do stuff.
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.