web-dev-qa-db-fra.com

Comment les constructeurs sont appelés lors de la sérialisation et de la désérialisation?

Comment les constructeurs sont appelés lors de la sérialisation et de la désérialisation

  1. Quand une classe implémente-t-elle sérialisable?
  2. Quand existe-t-il une relation parent/enfant et que seul l’implémentation enfant est-elle sérialisable?
  3. Lorsqu'il existe une relation parent/enfant et que les implémentations parent et enfant sont sérialisables?
46
Rekha

Exemple:

public class ParentDeserializationTest {

public static void main(String[] args){
    try {
        System.out.println("Creating...");
        Child c = new Child(1);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        c.field = 10;
        System.out.println("Serializing...");
        oos.writeObject(c);
        oos.flush();
        baos.flush();
        oos.close();
        baos.close();
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        System.out.println("Deserializing...");
        Child c1 = (Child)ois.readObject();
        System.out.println("c1.i="+c1.getI());
        System.out.println("c1.field="+c1.getField());
    } catch (IOException ex){
        ex.printStackTrace();
    } catch (ClassNotFoundException ex){
        ex.printStackTrace();
    }
}

public static class Parent {
    protected int field;
    protected Parent(){
        field = 5;
        System.out.println("Parent::Constructor");
    }
    public int getField() {
        return field;
    }
}

public static class Child extends Parent implements Serializable{
    protected int i;
    public Child(int i){
        this.i = i;
        System.out.println("Child::Constructor");
    }
    public int getI() {
        return i;
    }
}

}

Sortie:

Creating...
Parent::Constructor
Child::Constructor
Serializing...
Deserializing...
Parent::Constructor
c1.i=1
c1.field=5

Donc, si vous avez désérialisé votre objet, ses constructeurs ne sont pas appelés, mais le constructeur par défaut de son parent sera appelé. Et n'oubliez pas: tout votre objet sérialisable doit avoir un constructeur standard sans paramètres. 

29
Denis Loshkarev

Lors de la désérialisation, le constructeur par défaut accessible est appelé pour la première classe de la hiérarchie d'héritage qui n'implémente pas Serializable. 

> Une classe Serializable doit avoir accès au constructeur no-arg de sa première super-classe non sérialisable

42
szhem

Tout d’abord au moment de la désérialisation, aucun constructeur n’appelle, la valeur de tous les champs sera définie par réflexion.

Si vous marquez votre classe comme étant Sérialisable plus que JVM, définissez la valeur du champ par réflexion au moment de la désérialisation, puis la JVM recherchera sa super classe. Si elle n'est pas marquée comme Serializable, le constructeur par défaut appellera puis appellera la super classe suivante sur.

jetez un oeil à ce scénario:

import Java.io.File;
import Java.io.FileInputStream;
import Java.io.FileOutputStream;
import Java.io.IOException;
import Java.io.ObjectInputStream;
import Java.io.ObjectOutputStream;
import Java.io.Serializable;

public class Test {

    public static void main(String...strings) throws IOException, ClassNotFoundException {
        Employee emp = new Employee();
        emp.companyName = "XYZ";
        emp.employeeName = "ABC";

        getSirielization(emp);
        Employee em = (Employee) getDeSirielization();
        System.out.println(em.companyName+" "+em.employeeName);

    }

    public static void getSirielization(Object object) throws IOException {

        File f = new File("/home/server/ironman/serializedFile.txt");
        FileOutputStream fo = new FileOutputStream(f);
        ObjectOutputStream oob = new ObjectOutputStream(fo);
        oob.writeObject(object);
    }

    public static Object getDeSirielization() throws IOException, ClassNotFoundException {

        File f = new File("/home/server/ironman/serializedFile.txt");
        FileInputStream fo = new FileInputStream(f);
        ObjectInputStream oob = new ObjectInputStream(fo);
        Object object = oob.readObject();
        return object;
    }
}

class Company {
    String companyName;

    public Company() {
        System.out.println("Company-Default");
    }

}

class Employee extends Company implements Serializable {

    private static final long serialVersionUID = -3830853389460498676L;

    String employeeName;

    public Employee() {

        System.out.println("hello2");
    }
}
6
ritesh9984
  1. Si nous devons être précis, il n’existe pas de "classe unique". Chaque objet en Java étend la classe Object, qu’il s’agisse d’une superclasse directe ou d’une racine indirecte de sa hiérarchie. Donc, aucun constructeur ne fonctionnera, mais en prétendant que c'était le cas, nous ne recréons pas un certain objet, nous en créons simplement un nouveau.

  2. Lorsqu'il existe une relation parent/enfant, cela dépend si le parent est sérialisable ou non. Si le parent n'est PAS sérialisable, le super constructeur s'exécutera! Si le parent et l'enfant sont sérialisables, aucun constructeur n'est appelé.

Plus d'informations?

http://www.Java-questions.com/Serialization_interview_questions.html

6
Mechkov

Comment les constructeurs sont appelés lors de la sérialisation et de la désérialisation

  1. Quand une classe implémente-t-elle sérialisable?

  2. Quand existe-t-il une relation parent/enfant et que seul l'enfant implémente-t-il sérialisable?

  3. Lorsqu'il existe une relation parent/enfant et que les implémentations parent et enfant sont sérialisables?

À mon avis, la réponse à votre question est la suivante:

1) Si une classe implémente sérialisable et que seule cette classe existe, il n’existe pas de classe parent. dans ce cas c'est la classe d'objet. Ainsi, le constructeur No-arg de la classe Object sera exécuté et créera un objet factice. Lors de l'appel, le champ readObject () sera défini par réflexion et les données sauvegardées en mémoire ou dans un fichier.

2) si seul l'enfant implémente sérialisable, le flux ira jusqu'à la classe de base qui n'est pas sérialisable. si la classe de base dierect n'est pas sérialisée, alors (cette classe devrait avoir le constructeur NO-Arg), le constructeur NO-Arg s'exécutera pour la classe de base dans ce cas.

3) si tous les parents sont sérialisés, le flux passe à la classe Object et le constructeur No-Arg exécute la classe Object.

Remarque: Mais vous pouvez sérialiser en implémentant une interface externalisable, puis le constructeur par défaut (NO-ARG) sera appelé uniquement de cette classe et non de la classe parente lors du processus de désérialisation.

6
Prashant

Le processus de désérialisation n'utilise pas le constructeur de l'objet - l'objet est instancié sans constructeur et initialisé à l'aide des données d'instance sérialisées. La seule exigence imposée au constructeur pour une classe qui implémente Serializable est que la première superclasse non sérialisable de sa hiérarchie d'héritage doit avoir un constructeur sans argument.

0
Kingshuk Saha