Sérialisation des objets en Java : guide complet avec exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Sérialisation des objets en Java : des bases aux techniques avancées

\n\n

La sérialisation est le processus de conversion de l'état d'un objet en un flux d'octets pour le sauvegarder (dans un fichier, une base de données) ou le transmettre sur un réseau. Le processus inverse — la désérialisation — restaure l'objet à partir du flux d'octets. En Java, ce mécanisme est intégré à la plateforme et largement utilisé dans les systèmes distribués, la mise en cache et les applications web. Dans cet article, nous allons voir comment fonctionne la sérialisation, quelles interfaces et classes sont impliquées, et comment implémenter correctement une sérialisation personnalisée.

\n\n

Les bases : l'interface Serializable

\n\n

Pour qu'un objet puisse être sérialisé, sa classe doit implémenter l'interface marqueur java.io.Serializable. Cette interface ne contient aucune méthode — elle indique simplement à la machine virtuelle que l'objet est autorisé à être sérialisé.

\n\n
import java.io.Serializable;\n\npublic class User implements Serializable {\n    private static final long serialVersionUID = 1L;\n    private String name;\n    private int age;\n\n    public User(String name, int age) {\n        this.name = name;\n        this.age = age;\n    }\n\n    @Override\n    public String toString() {\n        return "User{name='" + name + "', age=" + age + "}";\n    }\n}
\n\n

Le champ serialVersionUID est un identifiant unique de version de la classe. S'il n'est pas déclaré explicitement, la JVM le calculera automatiquement, mais cela peut entraîner une InvalidClassException lors de la désérialisation si la classe a changé. Il est recommandé de toujours le définir manuellement.

\n\n

Processus de sérialisation et de désérialisation

\n\n

Pour écrire un objet dans un flux, on utilise ObjectOutputStream, pour le lire — ObjectInputStream. Voici un exemple de base :

\n\n
import java.io.*;\n\npublic class SerializationDemo {\n    public static void main(String[] args) {\n        User user = new User("Alexei", 30);\n\n        // Sérialisation\n        try (FileOutputStream fos = new FileOutputStream("user.ser");\n             ObjectOutputStream oos = new ObjectOutputStream(fos)) {\n            oos.writeObject(user);\n            System.out.println("Objet sérialisé : " + user);\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n\n        // Désérialisation\n        try (FileInputStream fis = new FileInputStream("user.ser");\n             ObjectInputStream ois = new ObjectInputStream(fis)) {\n            User restoredUser = (User) ois.readObject();\n            System.out.println("Objet restauré : " + restoredUser);\n        } catch (IOException | ClassNotFoundException e) {\n            e.printStackTrace();\n        }\n    }\n}
\n\n

Lors de la désérialisation, le constructeur de l'objet n'est pas appelé — l'état est restauré directement à partir du flux. C'est une différence importante par rapport à la création normale d'un objet via new.

\n\n

Le mot-clé transient

\n\n

Il est parfois nécessaire d'exclure certains champs de la sérialisation, par exemple les mots de passe ou les calculs temporaires. Pour cela, on utilise le modificateur transient. Les champs marqués ainsi reçoivent des valeurs par défaut (0, null, false) lors de la sérialisation.

\n\n
public class UserWithPassword implements Serializable {\n    private static final long serialVersionUID = 1L;\n    private String login;\n    private transient String password; // ne sera pas sérialisé\n\n    public UserWithPassword(String login, String password) {\n        this.login = login;\n        this.password = password;\n    }\n\n    @Override\n    public String toString() {\n        return "User{login='" + login + "', password='" + password + "'}";\n    }\n}
\n\n

Après la désérialisation, le champ password sera null. C'est pratique pour la sécurité, mais nécessite une logique de restauration supplémentaire.

\n\n

Sérialisation personnalisée : les méthodes writeObject et readObject

\n\n

Si le comportement standard ne convient pas, il est possible de redéfinir les méthodes privées

Recommendations