JavaRush /Blog Java /Random-FR /Comment fonctionne la sérialisation en Java
ramhead
Niveau 13

Comment fonctionne la sérialisation en Java

Publié dans le groupe Random-FR
Dans cet article, nous expliquerons ce qu'est la sérialisation et comment elle fonctionne en Java. Comment fonctionne la sérialisation en Java - 1

Introduction

La sérialisation d'objets est la capacité d'un objet à stocker une copie complète de lui-même et de tout autre objet auquel il fait référence à l'aide d'un flux de sortie (par exemple, dans un fichier externe). De cette façon, l'objet peut être recréé à partir de la copie sérialisée (enregistrée) un peu plus tard, lorsque cela est nécessaire. La sérialisation d'objets, une nouvelle fonctionnalité introduite dans JDK 1.1, fournit une fonction permettant de convertir des groupes ou des objets individuels en un flux binaire ou un tableau d'octets, pour le stockage ou la transmission sur un réseau. Et comme indiqué, un flux binaire ou un tableau d'octets donné peut être reconverti en objets Java. Cela se produit principalement automatiquement grâce aux classes ObjectInputStreamet ObjectOutputStream. Le programmeur peut décider d'implémenter cette fonctionnalité en implémentant l'interface Serializablelors de la création de la classe. Le processus de sérialisation est également connu sous le nom de marshaling d'objets , tandis que la désérialisation est connue sous le nom de unmarshaling . La sérialisation est un mécanisme qui permet à un objet d'enregistrer une copie de lui-même et de tous les autres objets référencés par cet objet dans un fichier externe à l'aide du fichier ObjectOutputStream. Les objets enregistrés peuvent être des structures de données, des diagrammes, des objets de classe JFrameou tout autre objet, quel que soit leur type. Dans le même temps, la sérialisation stocke des informations sur le type d'un objet afin que ultérieurement, une fois désérialisées, ces informations soient utilisées pour recréer le type exact d'objet dont il s'agissait. Ainsi, la sérialisation offre les fonctionnalités suivantes :
  • Un système de stockage d'objets, c'est-à-dire : de sauvegarde de leurs propriétés dans un fichier externe, sur disque ou dans une base de données.
  • Système d'appel de procédure à distance.
  • Un système de distribution d'objets, par exemple, dans des composants logiciels tels que COM, COBRA.
  • Système d'identification des changements de données variables au fil du temps.
Pour bien comprendre le concept de sérialisation, vous devez avoir une compréhension claire des deux autres concepts : la persistance des objets et la persistance des threads. Ici, nous parlerons un peu de chacun d'eux afin de nous en souvenir. Une explication complète de ceux-ci nécessiterait un chapitre distinct pour chacun de ces concepts.

Ruisseaux:

Chaque programme doit écrire ses données dans un emplacement de stockage ou un canal, et chaque programme doit lire les données à partir d'un canal ou d'un emplacement de stockage. En Java, ces canaux sur lesquels les programmes écrivent et à partir desquels les programmes lisent des données sont appelés Streams ( Stream) . Comment fonctionne la sérialisation en Java - 2
Figure 1. Représentation graphique des threads
Les flux sont principalement divisés en deux types :
  • Classes de flux d'octets appelées *Streams
  • Classes de flux de caractères appelées *Reader et *Writer
Chaque flux d'écriture de données contient un ensemble de méthodes d'écriture. Et chaque thread de lecture de données dispose donc d’un ensemble similaire de méthodes de lecture. Une fois le thread créé, toutes ces méthodes doivent être appelées.

Persistance

La persistance d'un objet est la capacité d'un objet à vivre ou, en d'autres termes, à « survivre » à l'exécution d'un programme. Cela signifie que tout objet créé au moment de l'exécution est détruit par le récupérateur JVM chaque fois que cet objet n'est plus utilisé. Mais si l'API de persistance est implémentée, ces objets ne seront pas détruits par le scavenger JVM, mais ils seront autorisés à « vivre », ce qui permettra également d'y accéder au prochain lancement de l'application. En d’autres termes, la persistance signifie qu’il existe une durée de vie pour un objet, indépendante de la durée de vie de l’application en cours d’exécution. Une façon d'implémenter la persistance consiste à stocker les objets quelque part dans un fichier ou une base de données externe, puis à les restaurer ultérieurement en utilisant ces fichiers ou la base de données comme sources. C'est là que la sérialisation entre en jeu. Tout objet non persistant existe tant que la JVM est en cours d'exécution. Les objets sérialisés sont simplement des objets convertis en flux, qui sont ensuite enregistrés dans un fichier externe ou transférés sur un réseau pour stockage et récupération.

Implémentation de l'interface Serialisable

Toute classe doit implémenter une interface java.io.Serializablepour sérialiser les objets de cette classe. L'interface Serializablen'a aucune méthode et marque uniquement la classe afin qu'elle puisse être identifiée comme sérialisable. Seuls les champs d'un objet de classe sérialisé peuvent être enregistrés. Les méthodes ou les constructeurs ne sont pas stockés dans le cadre du flux sérialisé. Si un objet agit comme une référence à un autre objet, alors les champs de cet objet sont également sérialisés si la classe de cet objet implémente l'interface Serializable. Autrement dit, le graphe de cet objet ainsi obtenu est totalement sérialisable. Un graphique d'objets comprend une arborescence ou une structure de champs d'un objet et de ses sous-objets. Deux classes principales qui aident à implémenter l'interfaceSeriliazable :
  • ObjectInputStream
  • ObjectOutputStream
Listing 1. Exemple de classe simple pour afficher la sérialisation
import java.io.*;
public class RandomClass implements Serializable {
 // Генерация рандомного значения
 private static int r() {
        return (int)(Math.random() * 10);
 }
    private int data[];
    // Конструктор
public RandomClass() {
        datafile = new int[r()];
        for (int i=0; i<datafile.length; i++)
        datafile[i]=r();
 }
    public void printout() {
 System.out.println("This RandomClass has "+datafile.length+" random integers");
 for (int i=0; i<datafile.length; i++) {
        System.out.print(datafile[i]+":");
        System.out.println();
    }
}
Dans le code ci-dessus, une classe sérialisable est créée car "marqué" par l'interface de sérialisation. La classe crée un tableau d'entiers aléatoires lorsqu'une instance de celle-ci est créée. Le code ci-dessous montre la possibilité d'écrire des objets dans un flux à l'aide du ObjectOutputStream. Le programme dispose d'un tableau d'entiers, mais pour la sérialisation, nous n'avons pas besoin de parcourir ses objets internes. L'interface Seriliazables'en charge automatiquement. Listing 2. Un exemple simple de sérialisation d'objets pour la sortie dans un fichier
import java.io.*;
import java.util.*;
public class OutSerialize {
    public static void main (String args[]) throws IOException {
        RandomClass rc1 = new RandomClass();
        RandomClass rc2 = new RandomClass();
//создание цепи потоков с потоком вывода an object в конце
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("objects.dat"));
        Date now = new Date(System.currentTimeMillis());
//java.util.* был импортирован для использования класса Date
        out.writeObject(now);
        out.writeObject(rc1);
        out.writeObject(rc2);
out.close();
        System.out.println("I have written:");
System.out.println("A Date object: "+now);
        System.out.println("Two Group of randoms");
rc1.printout();
rc2.printout();
 }
}
Le code ci-dessous démontre les capacités de la classe ObjectInputStream, qui lit les données sérialisées d'un fichier externe dans un programme. Notez que les objets sont lus dans le même ordre dans lequel ils ont été écrits dans le fichier. Listing 3. Lecture d'objets sérialisés ou désérialisation
import java.io.*;
import java.util.*;
public class InSerialize {
 public static void main (String args[]) throws  IOException, ClassNotFoundException {
    ObjectInputStream in =  new ObjectInputStream (new FileInputStream("objects.dat"));
 Date d1 = (Date)in.readObject();
 RandomClass rc1 = (RandomClass)in.readObject();
    RandomClass rc2 = (RandomClass)in.readObject();
    System.out.println("I have read:");
    System.out.println("A Date object: "+d1);
    System.out.println("Two Group of randoms");
    rc1.printout();
rc2.printout();
 }
}
Presque toutes les classes Java peuvent être sérialisées, y compris les classes AWT. Un frame, qui est une fenêtre, contient un ensemble de composants graphiques. Si la trame est sérialisée, le moteur de sérialisation s'en charge et sérialise tous ses composants et données (position, contenu, etc.). Certains objets de classe Java ne peuvent pas être sérialisés car ils contiennent des données faisant référence à des ressources éphémères du système d'exploitation. Par exemple les classes java.io.FileInputStreamet java.lang.Thread. Si un objet contient des références à des éléments non sérialisables, toute l'opération de sérialisation échouera et une exception sera levée NotSerializableException. Si un objet fait référence à une référence d'un objet non sérialisé, il peut alors être sérialisé à l'aide du mot-clé transient . Listing 4. Création d'objets sérialisables à l'aide du mot-clé transient
public class Sclass implements Serializable{
public transient Thread newThread;
//помните, что поток(поток параллельного исполнения) по умолчанию не сериализуемый класс
    private String studentID;
    private int sum;
}

Sécurité dans la sérialisation

La sérialisation d'une classe en Java implique de transmettre toutes ses données vers un fichier externe ou une base de données via un flux. Nous pouvons limiter les données qui seront sérialisées quand nous le souhaitons. Il y a deux façons de faire ça:
  • Chaque paramètre de classe déclaré comme transitoire n'est pas sérialisé (par défaut, tous les paramètres de classe sont sérialisés)
  • Ou bien, chaque paramètre de la classe que l'on souhaite sérialiser est marqué d'une balise Externalizable(par défaut, aucun paramètre n'est sérialisé).
Un champ de données ne sera pas sérialisé avec ObjectOutputStream, lorsqu'il est appelé sur un objet, si le champ de données de cet objet est marqué transient . Par exemple: private transient String password. D'un autre côté, pour déclarer explicitement les données d'un objet comme sérialisables, nous devons marquer la classe comme écrivant et lisant ExternalizablewriteExternalexplicitement readExteranlles données de cet objet.

Conclusion

La fonctionnalité de sérialisation des objets est utilisée dans de nombreux systèmes distribués comme moyen de transférer des données. Mais la sérialisation révèle des détails cachés, détruisant ainsi l'authenticité des types de données abstraits, ce qui détruit à son tour l'encapsulation. Dans le même temps, il est bon de savoir que les données de l'objet sérialisé sont les mêmes que celles de l'objet d'origine. C'est également une excellente opportunité d'implémenter une interface ObjectInputValidationet de surcharger une méthode validateObject(), même si plusieurs lignes de code sont utilisées. Si l'objet n'est pas trouvé, nous pouvons alors lancer une exception appropriée InvalidObjectException. Article original : Comment fonctionne la sérialisation en Java
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION