Sérialisation et désérialisation en Java

JavaJavaBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

La sérialisation et la désérialisation sont des processus importants en Java qui nous permettent de convertir un objet en un flux d'octets et de le restaurer ensuite en un objet respectivement. Nous pouvons utiliser la sérialisation et la désérialisation pour enregistrer ou conserver l'état des objets, ou pour transmettre des objets sur un réseau. Dans ce laboratoire, nous allons apprendre à sérialiser et à désérialiser des objets en Java à l'aide des classes ObjectInputStream et ObjectOutputStream.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/FileandIOManagementGroup(["File and I/O Management"]) java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/class_attributes("Class Attributes") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/constructors("Constructors") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/modifiers("Modifiers") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/serialization("Serialization") java/FileandIOManagementGroup -.-> java/io("IO") java/SystemandDataProcessingGroup -.-> java/object_methods("Object Methods") subgraph Lab Skills java/classes_objects -.-> lab-117950{{"Sérialisation et désérialisation en Java"}} java/class_attributes -.-> lab-117950{{"Sérialisation et désérialisation en Java"}} java/constructors -.-> lab-117950{{"Sérialisation et désérialisation en Java"}} java/modifiers -.-> lab-117950{{"Sérialisation et désérialisation en Java"}} java/serialization -.-> lab-117950{{"Sérialisation et désérialisation en Java"}} java/io -.-> lab-117950{{"Sérialisation et désérialisation en Java"}} java/object_methods -.-> lab-117950{{"Sérialisation et désérialisation en Java"}} end

Implémentez l'interface Serializable

Pour rendre nos objets sérialisables, nous devons implémenter l'interface Serializable. Il s'agit d'une interface marqueur qui ne nécessite pas l'implémentation de méthodes. L'interface Serializable est utilisée pour indiquer à la JVM que les objets de cette classe peuvent être sérialisés.

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;

    // Constructeur et méthodes getter/setter
}

Créez des objets à sérialiser

Créez quelques objets de la classe Student que nous allons sérialiser dans les étapes suivantes.

Student student1 = new Student("Alice", 22);
Student student2 = new Student("Bob", 21);

Sérialisez des objets

Pour sérialiser un objet, nous devons créer une instance de ObjectOutputStream et appeler sa méthode writeObject() en passant l'objet que nous voulons sérialiser. Cela écrira l'objet sous forme d'un flux d'octets dans un fichier que nous pourrons plus tard utiliser pour la désérialisation.

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

public class SerializationDemo {
    public static void main(String[] args) {
        try {
            FileOutputStream fileOut = new FileOutputStream("students.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);

            out.writeObject(student1);
            out.writeObject(student2);

            out.close();
            fileOut.close();

            System.out.println("Les données sérialisées sont enregistrées dans le fichier students.ser");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Désérialisez des objets

Pour désérialiser un objet, nous devons créer une instance de ObjectInputStream et appeler sa méthode readObject() pour lire le flux d'octets à partir du fichier que nous avons sérialisé précédemment. Cela renverra un objet que nous pourrons ensuite convertir en notre type de classe d'origine.

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

public class SerializationDemo {
    public static void main(String[] args) {
        try {
            FileInputStream fileIn = new FileInputStream("students.ser");
            ObjectInputStream in = new ObjectInputStream(fileIn);

            Student student1 = (Student) in.readObject();
            Student student2 = (Student) in.readObject();

            in.close();
            fileIn.close();

            // Affichez les étudiants
            System.out.println(student1);
            System.out.println(student2);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Gérer les champs transitoires

Si nous avons des champs dans notre classe que nous ne voulons pas sérialisés, nous pouvons les déclarer comme transitoires. Les champs transitoires sont ignorés lors de la sérialisation et de la désérialisation. Par exemple, ajoutons un champ transient à notre classe Student que nous ne voulons pas sérialiser :

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;
    private transient String password;

    //Constructeur, méthodes getter/setter
}

Personnaliser la sérialisation et la désérialisation

Nous pouvons également personnaliser le processus de sérialisation et de désérialisation en implémentant les méthodes writeObject() et readObject(). Cela peut être utile si nous voulons gérer les champs transitoires, ou si nous voulons effectuer un traitement supplémentaire lors de la sérialisation et de la désérialisation.

private void writeObject(ObjectOutputStream oos) throws IOException {
    // Sérialisation par défaut
    oos.defaultWriteObject();

    // Chiffrer le mot de passe avant de l'écrire dans le fichier
    String encryptedPassword = encrypt(password);
    oos.writeObject(encryptedPassword);
}

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
    // Désérialisation par défaut
    ois.defaultReadObject();

    // Déchiffrer le mot de passe après avoir lu le fichier
    String encryptedPassword = (String) ois.readObject();
    password = decrypt(encryptedPassword);
}

Gérer la numérotation des versions

Si nous mettons à jour notre classe en ajoutant ou en supprimant des propriétés, alors la version de la classe change, ce qui peut entraîner des erreurs lors de la désérialisation d'objets plus anciens. Nous pouvons gérer la numérotation des versions en utilisant le champ serialVersionUID pour spécifier un identifiant unique pour notre classe. Cela garantira que la sérialisation et la désérialisation fonctionneront correctement même si la définition de la classe change.

import java.io.Serializable;

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;
    private int age;

    //Constructeur, méthodes getter/setter
}

Exécutez le code

Compilez la classe SerializationDemo et exécutez-la dans le terminal en utilisant la commande suivante :

$ javac SerializationDemo.java
$ java SerializationDemo

La sortie devrait afficher les données sérialisées et les objets désérialisés.

Modifiez la classe Student

Mettez à jour la classe Student en ajoutant ou en supprimant un champ :

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;
    private int age;
    private String email; // Ajout d'un champ

    //Constructeur, méthodes getter/setter
}

Gérer la numérotation des versions avec serialVersionUID

Maintenant que nous avons modifié notre classe, nous devons gérer la numérotation des versions en mettant à jour le serialVersionUID. Cela garantira que nous pourrons toujours désérialiser les objets qui ont été sérialisés avant la modification de la classe.

public class Student implements Serializable {
    private static final long serialVersionUID = 2L;

    private String name;
    private int age;
    private String email; // Ajout d'un champ

    //Constructeur, méthodes getter/setter
}

Récapitulatif

Dans ce laboratoire, nous avons appris à sérialiser et à désérialiser des objets en Java à l'aide de ObjectInputStream et ObjectOutputStream. Nous avons également appris à gérer les champs transient, à personnaliser le processus de sérialisation et de désérialisation, et à gérer la numérotation des versions à l'aide de serialVersionUID. La sérialisation et la désérialisation sont des processus importants pour enregistrer et transmettre des données en Java, et nous pouvons les utiliser pour stocker l'état actuel de nos objets et les restaurer plus tard si nécessaire.