59 votes

Comment les constructeurs sont-ils appelés pendant la sérialisation et la désérialisation ?

Comment les constructeurs sont-ils appelés pendant la sérialisation et la désérialisation ?

  1. Quand il y a une classe qui implémente le sérielizable ?
  2. Quand il y a une relation parent/enfant et que seul l'enfant implémente le sérielizable ?
  3. Lorsqu'il y a une relation parent/enfant et que le parent et l'enfant implémentent tous deux le sérielizable ?

45voto

mijer Points 1971

Pendant 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 sérialisable doit avoir accès au constructeur sans argument de sa première superclasse non sérialisable.

32voto

Denis Loshkarev Points 199

Ejemplo:

 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

Ainsi, si vous désérialisez votre objet, ses constructeurs ne seront pas appelés, mais le constructeur par défaut de son parent sera appelé. Et n'oubliez pas : tous vos objets sérialisables doivent avoir un constructeur standard sans paramètres.

7voto

ritesh9984 Points 318

Tout d'abord, au moment de la désérialisation, sans qu'aucun constructeur ne soit appelé, la valeur de tous les champs sera fixée par réflexion.

Si vous marquez votre classe comme Serializable, la JVM fixe la valeur du champ par réflexion au moment de la désérialisation et après cela, la JVM recherche sa super classe et si celle-ci n'est pas marquée comme Serializable, le constructeur par défaut sera appelé, puis la super classe suivante et ainsi de suite.

Jetez un coup d'œil à 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");
    }
}

6voto

Mechkov Points 2603
  1. Si l'on veut être précis, il n'existe pas de "classe unique". Chaque objet en Java étend la classe Object, que ce soit en tant que superclasse directe ou racine indirecte de sa hiérarchie. Aucun constructeur ne sera donc exécuté, mais si tel était le cas, nous ne recréons pas un certain objet, nous en créons simplement un nouveau.

  2. Lorsqu'il y a une relation parent/enfant, cela dépend si le parent est sériable 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

6voto

Prashant Points 2490

Comment les constructeurs sont-ils appelés pendant la sérialisation et la désérialisation ?

  1. Quand il y a une classe qui implémente le sérielizable ?

  2. Quand il y a une relation parent/enfant et que seul l'enfant implémente le sérielizable ?

  3. Lorsqu'il y a une relation parent/enfant et que le parent et l'enfant implémentent tous deux le sérielizable ?

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

1) Si une classe implémente la sérialisation et que seule cette classe existe, il n'y a pas de classe mère. Le flux du constructeur est comme un constructeur par défaut qui sera appelé par la classe parente qui n'a pas mis en œuvre la sérialisation. Dans ce cas, il s'agit de la classe Object. Ainsi, le constructeur sans argument de la classe Object sera exécuté et créera un objet factice et, en appelant readObject(), le champ sera défini par réflexion et les données seront enregistrées dans la mémoire ou le fichier.

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

3) si tous les parents sont sérialisés, le flux ira vers la classe Object et le constructeur No-Arg sera exécuté de la classe Object.

Note : Mais vous pouvez sérialiser en implémentant l'interface externalisable alors le constructeur par défaut (NO-ARG) sera appelé de cette classe seulement et non de la classe parent lors du processus de désérialisation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X