↑
CHAPITRE 10.2

Sérialisation

Convertir des objets en flux binaire et les restaurer
La sérialisation permet de convertir un objet en un flux d'octets pour le stocker dans un fichier ou l'envoyer sur un réseau. La désérialisation permet de reconstruire l'objet à partir du flux.

10.2Sérialisation

10.2.1 – Principe

La sérialisation est le processus de conversion d'un objet Java en un flux d'octets pour le stocker dans un fichier ou l'envoyer sur un réseau. La désérialisation est le processus inverse qui reconstruit l'objet à partir du flux.

🔑 Interface Serializable

Pour qu'une classe soit sérialisable, elle doit implémenter l'interface Serializable. Cette interface est un marqueur (marker interface) : elle n'a pas de méthodes à implémenter.

Exemple : Classe sérialisable

import java.io.Serializable;

public class Personne implements Serializable {
    private static final long serialVersionUID = 1L;  // ID de version
    
    private String nom;
    private int age;
    private transient String motDePasse;  // transient : ne sera pas sérialisé
    
    public Personne(String nom, int age) {
        this.nom = nom;
        this.age = age;
    }
    
    // Getters et setters...
}

🆔 serialVersionUID

Le serialVersionUID est un identifiant de version utilisé par Java pour vérifier la compatibilité entre la version de la classe utilisée pour sérialiser un objet et celle utilisée pour le désérialiser. C'est une constante static final long.

Pourquoi utiliser serialVersionUID ?

Si vous ne déclarez pas explicitement un serialVersionUID, Java en génère un automatiquement basé sur la structure de la classe. Si vous modifiez la classe (ajout/suppression d'attributs, changement de méthodes), le serialVersionUID généré change, ce qui peut causer des erreurs lors de la désérialisation d'objets sérialisés avec une version antérieure.

Exemple : Classe avec serialVersionUID

import java.io.Serializable;

public class Personne implements Serializable {
    private static final long serialVersionUID = 1L;  // ID de version
    
    private String nom;
    private int age;
    private String email;  // Nouvel attribut ajouté plus tard
    
    public Personne(String nom, int age) {
        this.nom = nom;
        this.age = age;
    }
    
    // Getters et setters...
}
Fonctionnement :
  • Le serialVersionUID est une constante static final long
  • Il identifie la version de la classe pour la sĂ©rialisation
  • Si le serialVersionUID de la classe dĂ©sĂ©rialisĂ©e ne correspond pas Ă  celui de l'objet sĂ©rialisĂ©, une InvalidClassException est levĂ©e
  • En dĂ©clarant explicitement un serialVersionUID, vous pouvez contrĂ´ler la compatibilitĂ© entre versions

Générer un serialVersionUID

Vous pouvez générer un serialVersionUID de plusieurs façons :

  • Manuellement : Utiliser 1L pour commencer, puis l'incrĂ©menter Ă  chaque changement incompatible
  • Avec l'IDE : La plupart des IDE (IntelliJ, Eclipse) peuvent gĂ©nĂ©rer automatiquement un serialVersionUID
  • Avec la commande : Utiliser serialver en ligne de commande
Bonnes pratiques :
  • Toujours dĂ©clarer explicitement un serialVersionUID dans les classes sĂ©rialisables
  • Commencez avec 1L et incrĂ©mentez-le seulement si vous faites des changements incompatibles
  • Les changements compatibles (ajout d'attributs avec valeurs par dĂ©faut) ne nĂ©cessitent gĂ©nĂ©ralement pas de changer le serialVersionUID
  • Les changements incompatibles (suppression d'attributs, changement de types) nĂ©cessitent un nouveau serialVersionUID

🚫 Mot-clé transient

Le mot-clé transient indique qu'un attribut ne doit pas être sérialisé (utile pour les mots de passe, etc.).

public class Personne implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private String nom;
    private int age;
    private transient String motDePasse;  // Ne sera pas sérialisé
    
    // ...
}
Important : Les attributs transient ne sont pas sauvegardés lors de la sérialisation et seront null (ou valeur par défaut) après la désérialisation.

10.2.2 – Exemple simple

Voici un exemple complet de sérialisation et désérialisation d'un objet.

💾 Sérialisation

Exemple : Sérialiser un objet

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

Personne personne = new Personne("Alice", 25);

try (ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("personne.dat"))) {
    oos.writeObject(personne);
    System.out.println("Objet sérialisé avec succès");
} catch (IOException e) {
    System.out.println("Erreur : " + e.getMessage());
}

📂 Désérialisation

Exemple : Désérialiser un objet

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

try (ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("personne.dat"))) {
    Personne p = (Personne) ois.readObject();
    System.out.println("Nom : " + p.getNom());
    System.out.println("Âge : " + p.getAge());
} catch (IOException | ClassNotFoundException e) {
    System.out.println("Erreur : " + e.getMessage());
}

💡 Points clés à retenir

  • Serializable : Interface marqueur pour rendre une classe sĂ©rialisable
  • serialVersionUID : Identifiant de version pour la compatibilitĂ© entre versions de la classe
  • transient : Attributs non sĂ©rialisĂ©s
  • ObjectOutputStream : Pour sĂ©rialiser
  • ObjectInputStream : Pour dĂ©sĂ©rialiser
  • ClassNotFoundException : Peut ĂŞtre levĂ©e lors de la dĂ©sĂ©rialisation
  • InvalidClassException : Peut ĂŞtre levĂ©e si le serialVersionUID ne correspond pas
Conseil pratique : Toujours déclarer un serialVersionUID explicite dans vos classes sérialisables. Cela vous donne un contrôle sur la compatibilité des versions et évite les erreurs inattendues lors de la désérialisation d'objets créés avec des versions antérieures de votre classe.