2

I'm learning about Serialization and Inheritance and I don't understand who call the no-arg constructor at the deserialization process. The superclass A doesn't implement Serializable and subclass B extends A implements Serializable.

superclass A

public class A {

    int i;

    public A(int i) 
    {
        this.i = i;
    }

    public A()
    {
        i = 50;
        System.out.println("A's class constructor called");
    }  
}

subclass B

import java.io.Serializable;

public class B extends A implements Serializable {

    int j;

    // parameterized constructor
    public B(int i,int j) 
    {
        super(i);
        this.j = j;
    }
}

Driver Class

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Test {

    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 

        //Saving of object in a file
        FileOutputStream fos = new FileOutputStream("abc.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        // Method for serialization of B's class object
        oos.writeObject(b1);

        // closing streams
        oos.close();
        fos.close();

        System.out.println("Object has been serialized");

        // De-Serializing B's(subclass) object 

        // Reading the object from a file
        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();  // The A() constructor is called here

        // closing streams
        ois.close();
        fis.close();

        System.out.println("Object has been deserialized");

        System.out.println("i = " + b2.i);
        System.out.println("j = " + b2.j);
    }
}

If I delete the A() constructor I get the InvalidClassException. I see that A() is called when the b2 object is created but I don't understand why this A() is called at this statement and who called it.

When the b1 object is created the B(int i, int j) constructor and also A(int i) constructor are called. This is easy to understand. But I don't understand why A() constructor is called when b2 object is created.

elvis
  • 956
  • 9
  • 33
  • 56
  • 3
    See: https://stackoverflow.com/questions/8141440/how-are-constructors-called-during-serialization-and-deserialization – lexicore Apr 15 '18 at 14:12
  • Possible duplicate of [How are constructors called during serialization and deserialization?](https://stackoverflow.com/questions/8141440/how-are-constructors-called-during-serialization-and-deserialization) – Bogdan Lukiyanchuk Apr 15 '18 at 14:26

2 Answers2

2

From Serializable JavaDocs:

To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime.

Now to your question:

If I delete the A() constructor I get the InvalidClassException. I see that A() is called when the b2 object is created but I don't understand why this A() is called at this statement and who called it.

The A() constructor is called by the serialization mechanism via reflection. Specifically from ObjectInputStream via ObjectStreamClass.

lexicore
  • 42,748
  • 17
  • 132
  • 221
2

Because class A is non-serializable.

In java, when you creates an object, an object tree is created that contains all the object up in the hierarchy. In your case B -> A -> Object.

The purpose of serialization is to store the state of the object so that you could use it later.

When you deserialize it, java creates a new object without calling the constructor. The object would have lost its state if constructor get call(it may initialize to its default values).

Since class A is not serializable, it means its state does not get saved and java will create a new object by calling the default construcotr during deserialization. If it doesn't find default constructor, it will throw an exception during deserialization.

If you want to avoid this situation, please read writeReplace() and readResolve() methods

YogendraR
  • 2,144
  • 12
  • 17