![](/img/trans.png)
[英]While deserilization, Parent class(Not implementing the Serialization interface) constructor are called twice
[英]If the serialization is inherited in a hierarchy then the constructor of class not implementing serializable will be called. Why is this so?
當我反序列化以下示例中的SkinFruit和Banana2的構造函數時,為什么要調用Food and Fruit類的構造函數?
假設我有以下課程層次結構
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 + "" );
}
}
因為這就是反序列化的工作方式。 它是與常規對象構造不同的機制。
如果調用了Class A的構造函數,那是因為Class A本身未實現Serializable
。 反序列化期間,將調用繼承層次結構中第一個不可序列化類的無參數構造函數(可能是java.lang.Object
無參數構造函數)。 如果該類沒有無參數的構造函數,則將發生異常。
兩者都不被調用,因為您的類不可序列化。
您不能不調用B()
就調用A()
因為B調用了A。
考慮以下程序
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");
}
}
版畫
Inside class A
Inside class B
Inside class C
Inside class D
-------------
deserialize B
Inside class A
deserialize D
A是B的不可序列化的父級。它沒有被序列化,因此必須調用構造函數以設置需要設置的任何字段。 但是,B,C和D都是可序列化的,並且它們的字段已被序列化並將被重置。 無需調用構造函數。
如果您要在反序列化對象時完全重新創建一些信息,則應在Serializable
類中使用以下方法實現。 例如,將下面的代碼放入B
。
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("Resurrecting B");
}
另一個用於序列化,以防萬一您想在對象被注銷之前做一些事情。
private void writeObject(ObjectOutputStream out) throws IOException {
// do stuff.
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.