簡體   English   中英

如果序列化是在層次結構中繼承的,則將調用未實現可序列化的類的構造函數。 為什么會這樣呢?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM