Qu'est-ce que la sérialisation d'objets?

Réponses:

400

La sérialisation est la conversion d'un objet en une série d'octets, de sorte que l'objet peut être facilement enregistré dans un stockage persistant ou diffusé sur une liaison de communication. Le flux d'octets peut ensuite être désérialisé - converti en une réplique de l'objet d'origine.

TarkaDaal
la source
16
est-ce obligatoire? dois-je sérialiser les données avant de les envoyer? dans quel format est-il converti?
Francisco Corrales Morales
15
@FranciscoCorralesMorales - Dans les coulisses, toutes les données seront sérialisées avant d'être envoyées sur un flux. La quantité de travail que vous devez faire et le format de celle-ci dépendent tous deux de la plateforme et des bibliothèques que vous utilisez.
TarkaDaal
3
@FranciscoCorralesMorales Comment le dites-vous? Je veux dire que vous dites que le format dépend de la plate-forme et des bibliothèques. Je veux vraiment connaître le format.
JAVA
1
Est-il applicable uniquement aux objets? Peut-on sérialiser des variables (déclarées sans utiliser d'objets)?
Rumado
@Rumado Objects only
anKotliner
395

Vous pouvez considérer la sérialisation comme le processus de conversion d'une instance d'objet en une séquence d'octets (qui peut être binaire ou non selon l'implémentation).

Il est très utile lorsque vous souhaitez transmettre des données d'un objet à travers le réseau, par exemple d'une JVM à une autre.

En Java, le mécanisme de sérialisation est intégré à la plate-forme, mais vous devez implémenter l' interface Serializable pour rendre un objet sérialisable.

Vous pouvez également empêcher la sérialisation de certaines données de votre objet en marquant l'attribut comme transitoire .

Enfin, vous pouvez remplacer le mécanisme par défaut et fournir le vôtre; cela peut convenir dans certains cas particuliers. Pour ce faire, vous utilisez l'une des fonctionnalités cachées de java .

Il est important de noter que ce qui est sérialisé est la "valeur" de l'objet ou du contenu et non la définition de classe. Les méthodes ne sont donc pas sérialisées.

Voici un échantillon très basique avec des commentaires pour faciliter sa lecture:

import java.io.*;
import java.util.*;

// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {

    // These attributes conform the "value" of the object.

    // These two will be serialized;
    private String aString = "The value of that string";
    private int    someInteger = 0;

    // But this won't since it is marked as transient.
    private transient List<File> unInterestingLongLongList;

    // Main method to test.
    public static void main( String [] args ) throws IOException  { 

        // Create a sample object, that contains the default values.
        SerializationSample instance = new SerializationSample();

        // The "ObjectOutputStream" class has the default 
        // definition to serialize an object.
        ObjectOutputStream oos = new ObjectOutputStream( 
                               // By using "FileOutputStream" we will 
                               // Write it to a File in the file system
                               // It could have been a Socket to another 
                               // machine, a database, an in memory array, etc.
                               new FileOutputStream(new File("o.ser")));

        // do the magic  
        oos.writeObject( instance );
        // close the writing.
        oos.close();
    }
}

Lorsque nous exécutons ce programme, le fichier "o.ser" est créé et nous pouvons voir ce qui s'est passé derrière.

Si nous changeons la valeur de: someInteger en, par exemple Integer.MAX_VALUE , nous pouvons comparer la sortie pour voir quelle est la différence.

Voici une capture d'écran montrant précisément cette différence:

texte alternatif

Pouvez-vous repérer les différences? ;)

Il existe un champ supplémentaire pertinent dans la sérialisation Java: le serialversionUID mais je suppose que c'est déjà trop long pour le couvrir.

OscarRyz
la source
1
L' instance @ raam86 est l'objet en cours de sérialisation. Vous pouvez penser dans la méthode principale comme un programme séparé qui crée un objet de typeSerializationSample
OscarRyz
2
@ raam86 est la première instruction de la méthode principale: SerializationSample instance = new SerializationSample();ensuite la sortie est créée et l'objet écrit dans cette sortie.
OscarRyz
1
Oh. Je n'ai pas suivi assez près. Génial!!
raam86
1
@jacktrades Pourquoi ne l'essayez-vous pas? Copiez / collez simplement l'exemple et voyez "NotSerializableException" lancé :)
OscarRyz
1
@jacktrades parce que l'ordinateur n'a pas été informé que l'objet est autorisé à être sérialisé :) ce que l'on entend par oos?
Chris Bennett
101

Oser répondre à la question de 6 ans, en ajoutant juste une compréhension de très haut niveau pour les personnes novices en Java

Qu'est-ce que la sérialisation?

Conversion d'un objet en octets

Qu'est-ce que la désérialisation?

Reconversion des octets en un objet (désérialisation).

Quand la sérialisation est-elle utilisée?

Quand nous voulons persister l'objet. Lorsque nous voulons que l'objet existe au-delà de la durée de vie de la JVM.

Exemple du monde réel:

ATM: lorsque le titulaire du compte essaie de retirer de l'argent du serveur via ATM, les informations du titulaire du compte, telles que les détails du retrait, seront sérialisées et envoyées au serveur où les détails sont désérialisés et utilisés pour effectuer des opérations.

Comment la sérialisation est effectuée en Java.

  1. Implémenter l' java.io.Serializableinterface (interface marqueur donc pas de méthode à implémenter).

  2. Persister l'objet: utilisez la java.io.ObjectOutputStreamclasse, un flux de filtre qui est un wrapper autour d'un flux d'octets de niveau inférieur (pour écrire un objet dans des systèmes de fichiers ou transférer un objet aplati sur un câble réseau et reconstruit de l'autre côté).

    • writeObject(<<instance>>) - écrire un objet
    • readObject() - pour lire un objet sérialisé

Rappelles toi:

Lorsque vous sérialisez un objet, seul l'état de l'objet est enregistré, pas le fichier de classe ou les méthodes de l'objet.

Lorsque vous sérialisez un objet de 2 octets, vous voyez un fichier sérialisé de 51 octets.

Étapes de la sérialisation et de la désérialisation de l'objet.

Réponse pour: Comment s'est-il converti en fichier de 51 octets?

  • Écrit d'abord les données magiques du flux de sérialisation (STREAM_MAGIC = "AC ED" et STREAM_VERSION = version de la JVM).
  • Il écrit ensuite les métadonnées de la classe associées à une instance (longueur de la classe, nom de la classe, serialVersionUID).
  • Il écrit ensuite récursivement les métadonnées de la superclasse jusqu'à ce qu'il les trouve java.lang.Object.
  • Commence ensuite par les données réelles associées à l'instance.
  • Écrit enfin les données des objets associés à l'instance à partir des métadonnées vers le contenu réel.

Si vous êtes intéressé par des informations plus détaillées sur la sérialisation Java, veuillez consulter ce lien .

Edit : Un autre bon lien à lire.

Cela répondra à quelques questions fréquentes:

  1. Comment ne sérialiser aucun champ en classe.
    Rép: utilisez un mot-clé transitoire

  2. Lorsque la classe enfant est sérialisée, la classe parent est-elle sérialisée?
    Rép: Non, si un parent n'étend pas le champ des parents de l'interface sérialisable, ne soyez pas sérialisé.

  3. Lorsqu'un parent est sérialisé, la classe enfant est-elle sérialisée?
    Réponse: Oui, par défaut, la classe enfant est également sérialisée.

  4. Comment éviter que la classe enfant ne soit sérialisée?
    Rép: a. Substituez la méthode et le lancer writeObject et readObject NotSerializableException.

    b. vous pouvez également marquer tous les champs transitoires dans la classe enfant.

  5. Certaines classes au niveau du système telles que Thread, OutputStream et ses sous-classes et Socket ne sont pas sérialisables.
VdeX
la source
3
merci beaucoup pour cette réponse succincte, cela a été très utile!
Nobi
21

La sérialisation consiste à prendre un objet "vivant" en mémoire et à le convertir dans un format qui peut être stocké quelque part (par exemple en mémoire, sur disque) et plus tard "désérialisé" en un objet vivant.

Kent Boogaart
la source
14

J'ai aimé la façon dont @OscarRyz présente. Bien qu'ici, je continue l' histoire de la sérialisation qui a été à l'origine écrite par @amitgupta.

Même si connaître la structure des classes de robots et avoir des données sérialisées, le scientifique de la Terre n'a pas pu désérialiser les données qui peuvent faire fonctionner les robots.

Exception in thread "main" java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
:

Les scientifiques de Mars attendaient le paiement complet. Une fois le paiement effectué, les scientifiques de Mars ont partagé le serialversionUID avec les scientifiques de la Terre. Le scientifique de la Terre l'a mis en classe de robot et tout s'est bien passé.

noquery
la source
9

La sérialisation signifie des objets persistants en java. Si vous souhaitez enregistrer l'état de l'objet et reconstruire l'état ultérieurement (peut-être dans une autre JVM), la sérialisation peut être utilisée.

Notez que les propriétés d'un objet ne seront enregistrées que. Si vous souhaitez ressusciter l'objet à nouveau, vous devez avoir le fichier de classe, car seules les variables membres seront stockées et non les fonctions membres.

par exemple:

ObjectInputStream oos = new ObjectInputStream(                                 
                                 new FileInputStream(  new File("o.ser")) ) ;
SerializationSample SS = (SearializationSample) oos.readObject();

Le Searializable est une interface de marqueur qui indique que votre classe est sérialisable. L'interface de marqueur signifie qu'il s'agit simplement d'une interface vide et l'utilisation de cette interface informera la machine virtuelle Java que cette classe peut être rendue sérialisable.

Sathesh
la source
9

Mes deux cents de mon propre blog:

Voici une explication détaillée de la sérialisation : (mon propre blog)

Sérialisation:

La sérialisation est le processus de persistance de l'état d'un objet. Il est représenté et stocké sous la forme d'une séquence d'octets. Cela peut être stocké dans un fichier. Le processus pour lire l'état de l'objet à partir du fichier et le restaurer est appelé désérialisation.

Quel est le besoin de sérialisation?

Dans l'architecture moderne, il est toujours nécessaire de stocker l'état de l'objet, puis de le récupérer. Par exemple, dans Hibernate, pour stocker un objet, nous devons rendre la classe Serializable. Ce qu'il fait, c'est qu'une fois que l'état de l'objet est enregistré sous forme d'octets, il peut être transféré vers un autre système qui peut alors lire l'état et récupérer la classe. L'état de l'objet peut provenir d'une base de données ou d'un jvm différent ou d'un composant distinct. Avec l'aide de la sérialisation, nous pouvons récupérer l'état de l'objet.

Exemple de code et explication:

Voyons d'abord la classe d'objets:

public class Item implements Serializable{

    /**
    *  This is the Serializable class
    */
    private static final long serialVersionUID = 475918891428093041L;
    private Long itemId;
    private String itemName;
    private transient Double itemCostPrice;
    public Item(Long itemId, String itemName, Double itemCostPrice) {
        super();
        this.itemId = itemId;
        this.itemName = itemName;
        this.itemCostPrice = itemCostPrice;
      }

      public Long getItemId() {
          return itemId;
      }

     @Override
      public String toString() {
          return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
       }


       public void setItemId(Long itemId) {
           this.itemId = itemId;
       }

       public String getItemName() {
           return itemName;
       }
       public void setItemName(String itemName) {
            this.itemName = itemName;
        }

       public Double getItemCostPrice() {
            return itemCostPrice;
        }

        public void setItemCostPrice(Double itemCostPrice) {
             this.itemCostPrice = itemCostPrice;
        }
}

Dans le code ci-dessus, on peut voir que la classe Item implémente Serializable .

Il s'agit de l'interface qui permet à une classe d'être sérialisable.

Maintenant, nous pouvons voir qu'une variable appelée serialVersionUID est initialisée en variable Long. Ce nombre est calculé par le compilateur en fonction de l'état de la classe et des attributs de classe. C'est le nombre qui aidera le jvm à identifier l'état d'un objet lorsqu'il lit l'état de l'objet à partir d'un fichier.

Pour cela, nous pouvons consulter la documentation Oracle officielle:

Le runtime de sérialisation associe à chaque classe sérialisable un numéro de version, appelé serialVersionUID, qui est utilisé lors de la désérialisation pour vérifier que l'expéditeur et le récepteur d'un objet sérialisé ont chargé des classes pour cet objet qui sont compatibles par rapport à la sérialisation. Si le récepteur a chargé une classe pour l'objet qui a un serialVersionUID différent de celui de la classe de l'expéditeur correspondant, la désérialisation entraînera une InvalidClassException. Une classe sérialisable peut déclarer son propre serialVersionUID explicitement en déclarant un champ nommé "serialVersionUID" qui doit être statique, final et de type long: ANY-ACCESS-MODIFIER statique final long serialVersionUID = 42L; Si une classe sérialisable ne déclare pas explicitement un serialVersionUID, le runtime de sérialisation calcule alors une valeur serialVersionUID par défaut pour cette classe en fonction de divers aspects de la classe, comme décrit dans la spécification de sérialisation d'objet Java (TM). Cependant, il est fortement recommandé que toutes les classes sérialisables déclarent explicitement les valeurs serialVersionUID, car le calcul serialVersionUID par défaut est très sensible aux détails de classe qui peuvent varier en fonction des implémentations du compilateur et peuvent ainsi entraîner des InvalidClassExceptions inattendues lors de la désérialisation. Par conséquent, pour garantir une valeur serialVersionUID cohérente sur différentes implémentations du compilateur java, une classe sérialisable doit déclarer une valeur serialVersionUID explicite. Il est également fortement conseillé que les déclarations explicites serialVersionUID utilisent le modificateur privé dans la mesure du possible,

Si vous avez remarqué qu'il existe un autre mot-clé que nous avons utilisé, qui est transitoire .

Si un champ n'est pas sérialisable, il doit être marqué comme transitoire. Ici, nous avons marqué le itemCostPrice comme transitoire et ne voulons pas qu'il soit écrit dans un fichier

Voyons maintenant comment écrire l'état d'un objet dans le fichier, puis le lire à partir de là.

public class SerializationExample {

    public static void main(String[] args){
        serialize();
       deserialize();
    } 

    public static void serialize(){

         Item item = new Item(1L,"Pen", 12.55);
         System.out.println("Before Serialization" + item);

         FileOutputStream fileOut;
         try {
             fileOut = new FileOutputStream("/tmp/item.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut);
             out.writeObject(item);
             out.close();
             fileOut.close();
             System.out.println("Serialized data is saved in /tmp/item.ser");
           } catch (FileNotFoundException e) {

                  e.printStackTrace();
           } catch (IOException e) {

                  e.printStackTrace();
           }
      }

    public static void deserialize(){
        Item item;

        try {
                FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
                ObjectInputStream in = new ObjectInputStream(fileIn);
                item = (Item) in.readObject();
                System.out.println("Serialized data is read from /tmp/item.ser");
                System.out.println("After Deserialization" + item);
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
               e.printStackTrace();
        } catch (ClassNotFoundException e) {
               e.printStackTrace();
        }
     }
}

Dans ce qui précède, nous pouvons voir un exemple de sérialisation et de désérialisation d'un objet.

Pour cela, nous avons utilisé deux classes. Pour sérialiser l'objet, nous avons utilisé ObjectOutputStream. Nous avons utilisé la méthode writeObject pour écrire l'objet dans le fichier.

Pour la désérialisation, nous avons utilisé ObjectInputStream qui lit à partir de l'objet à partir du fichier. Il utilise readObject pour lire les données d'objet du fichier.

La sortie du code ci-dessus serait comme:

Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]

Notez que itemCostPrice de l'objet désérialisé est nul car il n'a pas été écrit.

Nous avons déjà discuté des bases de la sérialisation Java dans la partie I de cet article.

Maintenant, discutons-en profondément et comment cela fonctionne.

Commençons d'abord par le serialversionuid.

Le serialVersionUID est utilisé comme contrôle de version dans une classe Serializable.

Si vous ne déclarez pas explicitement un serialVersionUID, JVM le fera automatiquement pour vous, en fonction des différentes propriétés de la classe Serializable.

Algorithme de Java de calcul de serialversionuid (Lire plus de détails ici)

  1. Le nom de la classe.
    1. Les modificateurs de classe écrits sous la forme d'un entier 32 bits.
    2. Le nom de chaque interface trié par nom.
    3. Pour chaque champ de la classe trié par nom de champ (à l'exception des champs privés statiques et transitoires privés: le nom du champ. Les modificateurs du champ écrits sous la forme d'un entier 32 bits. Le descripteur du champ.
    4. S'il existe un initialiseur de classe, écrivez ce qui suit: Le nom de la méthode,.
    5. Le modificateur de la méthode, java.lang.reflect.Modifier.STATIC, écrit sous la forme d'un entier 32 bits.
    6. Le descripteur de la méthode, () V.
    7. Pour chaque constructeur non privé trié par nom et signature de méthode: Le nom de la méthode,. Les modificateurs de la méthode écrits sous la forme d'un entier 32 bits. Le descripteur de la méthode.
    8. Pour chaque méthode non privée triée par nom et signature de méthode: Le nom de la méthode. Les modificateurs de la méthode écrits sous la forme d'un entier 32 bits. Le descripteur de la méthode.
    9. L'algorithme SHA-1 est exécuté sur le flux d'octets produit par DataOutputStream et produit cinq valeurs de 32 bits sha [0..4]. La valeur de hachage est assemblée à partir des première et seconde valeurs 32 bits du condensé de message SHA-1. Si le résultat du résumé du message, les cinq mots de 32 bits H0 H1 H2 H3 H4, se trouve dans un tableau de cinq valeurs int nommées sha, la valeur de hachage serait calculée comme suit:
    long hash = ((sha[0] >>> 24) & 0xFF) |
>            ((sha[0] >>> 16) & 0xFF) << 8 |
>            ((sha[0] >>> 8) & 0xFF) << 16 |
>            ((sha[0] >>> 0) & 0xFF) << 24 |
>            ((sha[1] >>> 24) & 0xFF) << 32 |
>            ((sha[1] >>> 16) & 0xFF) << 40 |
>            ((sha[1] >>> 8) & 0xFF) << 48 |
>        ((sha[1] >>> 0) & 0xFF) << 56;

Algorithme de sérialisation Java

L'algorithme de sérialisation d'un objet est décrit ci-dessous:
1. Il écrit les métadonnées de la classe associée à une instance.
2. Il écrit récursivement la description de la superclasse jusqu'à ce qu'il trouve java.lang.object .
3. Une fois qu'il a fini d'écrire les informations de métadonnées, il commence alors par les données réelles associées à l'instance. Mais cette fois, cela part de la superclasse la plus haute.
4. Il écrit récursivement les données associées à l'instance, en commençant par la classe la moins superflue jusqu'à la classe la plus dérivée.

Choses à garder à l'esprit:

  1. Les champs statiques d'une classe ne peuvent pas être sérialisés.

    public class A implements Serializable{
         String s;
         static String staticString = "I won't be serializable";
    }
  2. Si le serialversionuid est différent dans la classe read, il lèvera une InvalidClassExceptionexception.

  3. Si une classe implémente sérialisable, toutes ses sous-classes seront également sérialisables.

    public class A implements Serializable {....};
    
    public class B extends A{...} //also Serializable
  4. Si une classe a une référence d'une autre classe, toutes les références doivent être sérialisables sinon le processus de sérialisation ne sera pas effectué. Dans ce cas, NotSerializableException est levée lors de l'exécution.

Par exemple:

public class B{
     String s,
     A a; // class A needs to be serializable i.e. it must implement Serializable
}
Pritam Banerjee
la source
1
«La sérialisation est le processus de sérialisation de l'état d'un objet qui est représenté et stocké sous la forme d'une séquence d'octets» n'a pas de sens. Si le serialVersionUIDest différent, il lancera un InvalidClassException, pas un ClassCastException. Il n'est pas nécessaire de gaspiller tout cet espace en spécifiant le serialVersionUIDcalcul. La documentation est citée, en longueur excessive, mais n'est pas liée ou correctement citée. Trop de peluches ici et trop d'erreurs.
Marquis de Lorne
«La sérialisation est le processus de sérialisation» reste vide de sens.
Marquis de Lorne
6

La sérialisation est le processus de conversion de l'état d'un objet en bits afin qu'il puisse être stocké sur un disque dur. Lorsque vous désérialisez le même objet, il conservera son état ultérieurement. Il vous permet de recréer des objets sans avoir à enregistrer les propriétés des objets à la main.

http://en.wikipedia.org/wiki/Serialization

Fromage Daneish
la source
"... afin qu'il puisse être stocké sur un disque dur." Ou transféré via un protocole binaire.
Jim Anderson, le
4

Sérialisation d'objets Java

entrez la description de l'image ici

Serializationest un mécanisme pour transformer un graphe d'objets Java en un tableau d'octets pour le stockage ( to disk file) ou la transmission ( across a network), puis en utilisant la désérialisation, nous pouvons restaurer le graphe des objets. Les graphiques des objets sont correctement restaurés à l'aide d'un mécanisme de partage de référence. Mais avant de stocker, vérifiez si serialVersionUID du fichier d'entrée / réseau et le fichier .class serialVersionUID sont identiques. Sinon, lancez a java.io.InvalidClassException.

Chaque classe versionnée doit identifier la version de classe d'origine pour laquelle elle est capable d'écrire des flux et à partir de laquelle elle peut lire. Par exemple, une classe versionnée doit déclarer:

Syntaxe serialVersionUID

// ANY-ACCESS-MODIFIER static final long serialVersionUID = (64-bit has)L;
private static final long serialVersionUID = 3487495895819393L;

serialVersionUID est essentiel au processus de sérialisation. Mais il est facultatif pour le développeur de l'ajouter dans le fichier source java. Si un serialVersionUID n'est pas inclus, le runtime de sérialisation générera un serialVersionUID et l'associera à la classe. L'objet sérialisé contiendra ce serialVersionUID avec d'autres données.

Remarque - Il est fortement recommandé que toutes les classes sérialisables déclarent explicitement un serialVersionUID since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, et peuvent ainsi entraîner des conflits de serialVersionUID inattendus pendant la désérialisation, entraînant l'échec de la désérialisation.

Inspection des classes sérialisables

entrez la description de l'image ici


Un objet Java est uniquement sérialisable. si une classe ou l'une de ses superclasses implémente soit l' interface java.io.Serializable , soit sa sous-interface, java.io.Externalizable .

  • Une classe doit implémenter l' interface java.io.Serializable afin de sérialiser son objet avec succès. Serializable est une interface de marqueur et utilisée pour informer le compilateur que la classe qui l'implémente doit être ajoutée au comportement sérialisable. Ici, Java Virtual Machine (JVM) est responsable de sa sérialisation automatique.

    transitoire Mot-clé: java.io.Serializable interface

    Lors de la sérialisation d'un objet, si nous ne voulons pas que certains membres de données de l'objet soient sérialisés, nous pouvons utiliser le modificateur transitoire. Le mot-clé transitoire empêchera ce membre de données d'être sérialisé.

    • Les champs déclarés comme transitoires ou statiques sont ignorés par le processus de sérialisation.

    TRANSITOIRE & VOLATILE

    +--------------+--------+-------------------------------------+
    |  Flag Name   |  Value | Interpretation                      |
    +--------------+--------+-------------------------------------+
    | ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached.|
    +--------------+--------+-------------------------------------+
    |ACC_TRANSIENT | 0x0080 | Declared transient; not written or  |
    |              |        | read by a persistent object manager.|
    +--------------+--------+-------------------------------------+
    class Employee implements Serializable {
        private static final long serialVersionUID = 2L;
        static int id;
    
        int eno; 
        String name;
        transient String password; // Using transient keyword means its not going to be Serialized.
    }
  • L'implémentation de l'interface externalisable permet à l'objet d'assumer un contrôle complet sur le contenu et le format du formulaire sérialisé de l'objet. Les méthodes de l'interface Externalizable, writeExternal et readExternal, sont appelées pour enregistrer et restaurer l'état des objets. Lorsqu'elles sont implémentées par une classe, elles peuvent écrire et lire leur propre état en utilisant toutes les méthodes d'ObjectOutput et ObjectInput. Il est de la responsabilité des objets de gérer les versions qui se produisent.

    class Emp implements Externalizable {
        int eno; 
        String name;
        transient String password; // No use of transient, we need to take care of write and read.
    
        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeInt(eno);
            out.writeUTF(name);
            //out.writeUTF(password);
        }
        @Override
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            this.eno = in.readInt();
            this.name = in.readUTF();
            //this.password = in.readUTF(); // java.io.EOFException
        }
    }
  • Seuls les objets qui prennent en charge l'interface java.io.Serializable ou java.io.Externalizable peuvent être written to/read from streams. La classe de chaque objet sérialisable est codée, y compris le nom de classe et la signature de la classe, les valeurs des champs et des tableaux de l'objet, et la fermeture de tout autre objet référencé à partir des objets initiaux.

Exemple sérialisable pour les fichiers

public class SerializationDemo {
    static String fileName = "D:/serializable_file.ser";

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        Employee emp = new Employee( );
        Employee.id = 1; // Can not Serialize Class data.
        emp.eno = 77;
        emp.name = "Yash";
        emp.password = "confidential";
        objects_WriteRead(emp, fileName);

        Emp e = new Emp( );
        e.eno = 77;
        e.name = "Yash";
        e.password = "confidential";
        objects_WriteRead_External(e, fileName);

        /*String stubHost = "127.0.0.1";
        Integer anyFreePort = 7777;
        socketRead(anyFreePort); //Thread1
        socketWrite(emp, stubHost, anyFreePort); //Thread2*/

    }
    public static void objects_WriteRead( Employee obj, String serFilename ) throws IOException{
        FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );
        objectOut.writeObject( obj );
        objectOut.close();
        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            FileInputStream fis = new FileInputStream( new File( serFilename ) );
            ObjectInputStream ois = new ObjectInputStream( fis );
            Object readObject;
            readObject = ois.readObject();
            String calssName = readObject.getClass().getName();
            System.out.println("Restoring Class Name : "+ calssName); // InvalidClassException

            Employee emp = (Employee) readObject;
            System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);

            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void objects_WriteRead_External( Emp obj, String serFilename ) throws IOException {
        FileOutputStream fos = new FileOutputStream(new File( serFilename ));
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );

        obj.writeExternal( objectOut );
        objectOut.flush();

        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            // create a new instance and read the assign the contents from stream.
            Emp emp = new Emp();

            FileInputStream fis = new FileInputStream(new File( serFilename ));
            ObjectInputStream ois = new ObjectInputStream( fis );

            emp.readExternal(ois);

            System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);

            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Exemple sérialisable sur réseau

Distribuer l'état de l'objet dans différents espaces d'adressage, soit dans différents processus sur le même ordinateur, soit même dans plusieurs ordinateurs connectés via un réseau, mais qui fonctionnent ensemble en partageant des données et en invoquant des méthodes.

/**
 * Creates a stream socket and connects it to the specified port number on the named host. 
 */
public static void socketWrite(Employee objectToSend, String stubHost, Integer anyFreePort) {
    try { // CLIENT - Stub[marshalling]
        Socket client = new Socket(stubHost, anyFreePort);
        ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
        out.writeObject(objectToSend);
        out.flush();
        client.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
// Creates a server socket, bound to the specified port. 
public static void socketRead(  Integer anyFreePort ) {
    try { // SERVER - Stub[unmarshalling ]
        ServerSocket serverSocket = new ServerSocket( anyFreePort );
        System.out.println("Server serves on port and waiting for a client to communicate");
            /*System.in.read();
            System.in.read();*/

        Socket socket = serverSocket.accept();
        System.out.println("Client request to communicate on port server accepts it.");

        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        Employee objectReceived = (Employee) in.readObject();
        System.out.println("Server Obj : "+ objectReceived.name );

        socket.close();
        serverSocket.close();
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

@voir

Yash
la source
1
Lorsque vous ajoutez une réponse à une question de six ans qui contient déjà plusieurs très bonnes réponses, vous devez faire beaucoup mieux qu'une cacophonie d'erreurs d'orthographe.
Marquis de Lorne
@ejp Downvoting est l'outil pour exprimer votre opinion négative. Être offensant et grossier à la limite est inacceptable.
Konstantinos Chertouras
1
@KonstantinosChertouras Donner des raisons pour le downvote est utile à l'affiche, et ce sont mes raisons, que vous les aimiez ou non comme vous le ferez.
Marquis de Lorne
Vous devez également éviter les erreurs telles que l'affirmation que la sérialisation a un objectif de sécurité. Ce n'est pas le cas.
Marquis de Lorne
@EJP J'ai mis à jour mon message, corrigé que la sérialisation n'est pas à des fins de sécurité, mais elle est utilisée pour transformer l'état d'un objet en n'importe quel stockage et pour récupérer l'état d'origine d'un objet à l'aide de SUID via le mécanisme de désérialisation. JVM to JVM
Yash
3

La sérialisation est le processus d'enregistrement d'un objet sur un support de stockage (tel qu'un fichier ou un tampon de mémoire) ou de le transmettre sur une connexion réseau sous forme binaire. Les objets sérialisés sont indépendants de la JVM et peuvent être re-sérialisés par n'importe quelle JVM. Dans ce cas, l'état des objets java "en mémoire" est converti en un flux d'octets. Ce type de fichier ne peut pas être compris par l'utilisateur. Il s'agit d'un type particulier d'objet c'est-à-dire réutilisé par la JVM (Java Virtual Machine). Ce processus de sérialisation d'un objet est également appelé dégonflage ou triage d'un objet.

L'objet à sérialiser doit implémenter java.io.SerializableInterface. Le mécanisme de sérialisation par défaut d'un objet écrit la classe de l'objet, la signature de classe et les valeurs de tous les champs non transitoires et non statiques.

class ObjectOutputStream extends java.io.OutputStream implements ObjectOutput,

ObjectOutputinterface étend l' DataOutputinterface et ajoute des méthodes pour sérialiser des objets et écrire des octets dans le fichier. L' interface ObjectOutputStreamétend java.io.OutputStreamet implémente ObjectOutput. Il sérialise des objets, des tableaux et d'autres valeurs dans un flux. Ainsi le constructeur de ObjectOutputStreams'écrit:

ObjectOutput ObjOut = new ObjectOutputStream(new FileOutputStream(f));

Le code ci-dessus a été utilisé pour créer l'instance de la ObjectOutputclasse avec le ObjectOutputStream( )constructeur qui prend l'instance de la FileOuputStreamcomme paramètre.

L' ObjectOutputinterface est utilisée en implémentant la ObjectOutputStreamclasse. Le ObjectOutputStreamest construit pour sérialiser l'objet.

Désérialisation d'un objet en Java

L'opération opposée de la sérialisation est appelée désérialisation, c'est-à-dire que l'extraction des données d'une série d'octets est appelée désérialisation, ce qui est également appelé gonflement ou dé-marshalling.

ObjectInputStreamétend java.io.InputStreamet implémente l' ObjectInput interface. Il désérialise les objets, les tableaux et autres valeurs d'un flux d'entrée. Ainsi le constructeur de ObjectInputStreams'écrit:

ObjectInputStream obj = new ObjectInputStream(new FileInputStream(f));

Le code ci-dessus du programme crée l'instance de la ObjectInputStreamclasse pour désérialiser ce fichier qui avait été sérialisé par la ObjectInputStreamclasse. Le code ci-dessus crée l'instance en utilisant l'instance de la FileInputStreamclasse qui contient l'objet fichier spécifié qui doit être désérialisé car le ObjectInputStream()constructeur a besoin du flux d'entrée.

Sindu
la source
2

Renvoyez le fichier en tant qu'objet: http://www.tutorialspoint.com/java/java_serialization.htm

        import java.io.*;

        public class SerializeDemo
        {
           public static void main(String [] args)
           {
              Employee e = new Employee();
              e.name = "Reyan Ali";
              e.address = "Phokka Kuan, Ambehta Peer";
              e.SSN = 11122333;
              e.number = 101;

              try
              {
                 FileOutputStream fileOut =
                 new FileOutputStream("/tmp/employee.ser");
                 ObjectOutputStream out = new ObjectOutputStream(fileOut);
                 out.writeObject(e);
                 out.close();
                 fileOut.close();
                 System.out.printf("Serialized data is saved in /tmp/employee.ser");
              }catch(IOException i)
              {
                  i.printStackTrace();
              }
           }
        }

    import java.io.*;
    public class DeserializeDemo
    {
       public static void main(String [] args)
       {
          Employee e = null;
          try
          {
             FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn);
             e = (Employee) in.readObject();
             in.close();
             fileIn.close();
          }catch(IOException i)
          {
             i.printStackTrace();
             return;
          }catch(ClassNotFoundException c)
          {
             System.out.println("Employee class not found");
             c.printStackTrace();
             return;
          }
          System.out.println("Deserialized Employee...");
          System.out.println("Name: " + e.name);
          System.out.println("Address: " + e.address);
          System.out.println("SSN: " + e.SSN);
          System.out.println("Number: " + e.number);
        }
    }
Ran Adler
la source
Cela ne répond pas aux parties «ce qui est» ou «veuillez expliquer» de la question.
Marquis de Lorne
1

| * | Sérialisation d'une classe: conversion d'un objet en octets et octets en objet (désérialisation).

class NamCls implements Serializable
{
    int NumVar;
    String NamVar;
}

| => La sérialisation d'objets est un processus de conversion de l'état d'un objet en vapeur d'octets.

  • | -> Implémentez lorsque vous souhaitez que l'objet existe au-delà de la durée de vie de la machine virtuelle Java.
  • | -> L'objet sérialisé peut être stocké dans la base de données.
  • | -> Les objets sérialisables ne peuvent pas être lus et compris par les humains afin que nous puissions assurer la sécurité.

| => Object-Deserialization est le processus d'obtention de l'état d'un objet et de le stocker dans un objet (java.lang.Object).

  • | -> Avant de stocker son état, il vérifie si le fichier d'entrée / réseau serialVersionUID et le fichier .class serialVersionUID sont identiques.
    & nbsp & nbspSi vous ne lancez pas java.io.InvalidClassException.

| => Un objet Java n'est sérialisable que si sa classe ou l'une de ses superclasses

  • implémente l'interface java.io.Serializable ou
  • sa sous-interface, java.io.Externalizable.

| => Les champs statiques d'une classe ne peuvent pas être sérialisés.

class NamCls implements Serializable
{
    int NumVar;
    static String NamVar = "I won't be serializable";;
}

| => Si vous ne voulez pas sérialiser une variable d'une classe, utilisez un mot-clé transitoire

class NamCls implements Serializable
{
    int NumVar;
    transient String NamVar;
}

| => Si une classe implémente sérialisable, toutes ses sous-classes seront également sérialisables.

| => Si une classe a une référence d'une autre classe, toutes les références doivent être sérialisables sinon le processus de sérialisation ne sera pas effectué. Dans ce cas,
NotSerializableException est levée lors de l'exécution.

Sujay UN
la source
0

Je proposerai une analogie pour aider potentiellement à solidifier le but conceptuel / l'aspect pratique de la sérialisation / désérialisation d' objets .

J'imagine la sérialisation / désérialisation d'un objet dans le contexte d'une tentative de déplacement d'un objet à travers un égout pluvial. L'objet est essentiellement "décomposé" ou sérialisé en des versions plus modulaires de lui-même - dans ce cas, une série d'octets - afin d'être effectivement autorisé à passer à travers un support. Dans un sens informatique, nous pourrions voir le chemin parcouru par les octets à travers le collecteur d'orage comme étant semblable aux octets voyageant à travers un réseau. Nous transmutons notre objet afin de nous conformer à un mode de transport ou un format plus souhaitable. L'objet sérialisé sera généralement stocké dans un fichier binaire qui pourra être lu ultérieurement, écrit dans ou les deux.

Peut-être qu'une fois que notre objet sera capable de glisser à travers le drain sous la forme d'une série d'octets décomposés, nous pourrions souhaiter stocker cette représentation de l'objet sous forme de données binaires dans une base de données ou un disque dur. Le principal point à retenir cependant, c'est qu'avec la sérialisation / désérialisation, nous avons la possibilité de laisser notre objet rester dans sa forme binaire après avoir été sérialisé, ou de "récupérer" la forme originale de l'objet en effectuant la désérialisation.

Benjamin Westburg
la source