简体   繁体   中英

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?

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 . During Deserialization, the parameterless constructor of the first non-serializable class in the inheritance hierarchy is called (possibly that of 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.

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. However, B, C and D are all Serializable and their fields have been serializable and will be reset. 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. For instance, put the below code inside 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.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM