Sérialisation

     

La classe ObjectOutputStream est une classe de fonctionnalités qui permet d'écrire des objets dans un flux binaire à l'aide de la méthode writeObject. Symétriquement la classe ObjectInputStream est une classe de fonctionnalités qui permet de lire des objets dans un flux binaire à l'aide de la méthode readObject. On appelle sérialisation la technique utilisée pour écrire ou lire des objets dans un flux binaire. La sérialisation peut servir à archiver des objets dans un fichier et permet de transmettre des objets à travers un réseau ; elle intervient aussi pour permettre à des applications de communiquer par des appels à des méthodes distantes, possibilité mise en oeuvre dans le système RMI (Remote Method Invocation). Le mécanisme inverse s'appelle la désérialisation.

Pour qu'un objet puisse être sérialisé, il est nécessaire que sa classe implémente l'interface java.io.Serializable. Cette interface ne contient aucune déclaration de méthode ; lorsqu'une classe implémente l'interface Serializable, elle « autorise » la sérialisation de ses instances. Beaucoup de classes de l'API sont sérialisables. On peut consulter les classes en ligne pour savoir celles qui sont sérialisables et celles qui ne le sont pas. Si on tente de sérialiser un objet d'une classe qui n'implémente pas l'interface Serializable, une exception java.io.NotSerializableException est lancée.

Les tableaux d'objets sérialisables ou de types primitifs sont sérialisables, comme on peut le voir à partir de l'exemple ci-dessous. Signalons que la classe ObjectOutputStream (resp. ObjectInputStream) possède aussi des méthodes pour écrire (resp. lire) tous les types primitifs : writeInt, ... (resp. readInt, ...) ou les chaînes de caractères.

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

class ClasseEssai implements Serializable {
    String chaine = "bonjour";
    int n = 1;
}

class Serialisation {
    public static void main(String[] arg) throws Exception {
	ObjectOutputStream sortie = new ObjectOutputStream
	    (new FileOutputStream("essai.don"));
	sortie.writeObject(new ClasseEssai());
	sortie.writeObject(new java.util.Date());
	int[] tableau1 = {10, 11, 12};
	sortie.writeObject(tableau1);
	Integer[] tableau2 = {new Integer(110), new Integer(111)};
	sortie.writeObject(tableau2);
	sortie.close();
	
	ObjectInputStream entree = new ObjectInputStream(new FileInputStream("essai.don"));
	ClasseEssai c = (ClasseEssai)entree.readObject();
	System.out.println(c.chaine);
	System.out.println(c.n);
	System.out.println(entree.readObject());
	int[] tableau3 = (int[])entree.readObject();
	System.out.println(tableau3[1]);
	Integer[]tableau4 = (Integer[])entree.readObject();
	System.out.println(tableau4[0]);
	entree.close();
    }
}
On obtient en sortie, à l'écran :
bonjour
1
Thu Feb 10 12:38:41 GMT+00:00 2000
11
110
Le programme se trouve ici.
implements Serializable : si on retire ceci, le fichier sera encore compilé avec succès mais une exception NotSerializableException se propagera à l'exécution dès qu'on tentera d'écrire une instance de cette classe dans le flux de sortie.
new java.util.Date() : ce constructeur construit une instance de la classe Date correspondant à l'instant de la construction ; cette classe est sérialisable.
sortie.writeObject(tableau1); : on peut sérialiser des tableaux de types primitifs.
sortie.writeObject(tableau2); : on peut sérialiser des tableaux d'objets sérialisables. La classe Integer implémente l'interface Serializable car elle hérite de la classe Number qui implémente directement cette interface.
(ClasseEssai)entree.readObject() : la méthode readObject renvoie un Object ; si on veut utiliser les spécificités de l'objet renvoyé, il faut effectuer une conversion de classe.

© Irène Charon, Télécom ParisTech 2011