Quelle est la différence entre sérialisable et Externalisable en Java?

Quelle est la différence entre Serializable et Externalizable en Java?

260
demandé sur Michael Myers 2009-05-03 23:58:19

12 réponses

pour ajouter aux autres réponses, en implémentant java.io.Serializable , vous obtenez la capacité de sérialisation" automatique " pour les objets de votre classe. Pas besoin de mettre en œuvre une autre logique, ça marchera. Le Java runtime utilisera la réflexion pour trouver comment marshal et unmarshal vos objets.

dans la version précédente de Java, la réflexion était très lente, et donc serializaing grands objets graphiques (par exemple dans les applications client-serveur RMI) était un peu un problème de performance. Pour gérer cette situation, l'interface java.io.Externalizable a été fournie, qui est comme java.io.Serializable mais avec des mécanismes écrits sur mesure pour effectuer les fonctions de marshalling et de unmarshalling (vous devez implémenter les méthodes readExternal et writeExternal sur votre classe). Cela vous donne les moyens de contourner le goulot d'étranglement de la performance de réflexion.

dans les versions récentes de Java (1.3 et suivantes, certainement) , la performance de la réflexion est bien meilleure qu'elle ne l'était, et donc c'est beaucoup moins un problème. Je pense que vous auriez du mal à obtenir un avantage significatif de Externalizable avec un JVM moderne.

en outre, le mécanisme de sérialisation Java intégré n'est pas le seul, vous pouvez obtenir des remplacements tiers, tels que la sérialisation JBoss, qui est considérablement plus rapide, et est un remplacement direct pour la valeur par défaut.

un grand inconvénient de Externalizable est que vous devez maintenir cette logique vous - même-si vous ajoutez, si vous supprimez ou modifiez un champ de votre classe, vous devez modifier vos méthodes writeExternal / readExternal pour en tenir compte.

en résumé, Externalizable est une relique de Java 1.1 jours. Il n'y a vraiment pas besoin de plus.

251
répondu skaffman 2011-07-18 16:11:19
La sérialisation

fournit une fonctionnalité par défaut pour stocker et recréer plus tard l'objet. Il utilise le format verbeux pour définir le graphique entier des objets à stocker, par exemple supposons que vous ayez une liste de liens et que vous codiez comme ci-dessous, alors la sérialisation par défaut va découvrir tous les objets qui sont liés et va sérialiser. Dans la sérialisation par défaut, l'objet est construit entièrement à partir de ses bits stockés, sans aucun appel de constructeur.

  ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream("/Users/Desktop/files/temp.txt"));
        oos.writeObject(linkedListHead); //writing head of linked list
        oos.close();

Mais si vous voulez restriction de la sérialisation ou ne veut pas qu'une partie de votre objet soit sérialisée puis utilisez Externalisable. L'interface Externalisable étend l'interface sérialisable et ajoute deux méthodes, writeExternal() et readExternal(). Ceux-ci sont automatiquement appelés lors de la sérialisation ou de la desérialisation. Tout en travaillant avec Externalisable nous devrions nous rappeler que le constructeur par défaut devrait être public sinon le code fera exception. S'il vous plaît suivre le code ci-dessous:

public class MyExternalizable implements Externalizable
{

private String userName;
private String passWord;
private Integer roll;

public MyExternalizable()
{

}

public MyExternalizable(String userName, String passWord, Integer roll)
{
    this.userName = userName;
    this.passWord = passWord;
    this.roll = roll;
}

@Override
public void writeExternal(ObjectOutput oo) throws IOException 
{
    oo.writeObject(userName);
    oo.writeObject(roll);
}

@Override
public void readExternal(ObjectInput oi) throws IOException, ClassNotFoundException 
{
    userName = (String)oi.readObject();
    roll = (Integer)oi.readObject();
}

public String toString()
{
    StringBuilder b = new StringBuilder();
    b.append("userName: ");
    b.append(userName);
    b.append("  passWord: ");
    b.append(passWord);
    b.append("  roll: ");
    b.append(roll);

    return b.toString();
}
public static void main(String[] args)
{
    try
    {
        MyExternalizable m  = new MyExternalizable("nikki", "student001", 20);
        System.out.println(m.toString());
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/Desktop/files/temp1.txt"));
        oos.writeObject(m);
        oos.close();

        System.out.println("***********************************************************************");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/Desktop/files/temp1.txt"));
        MyExternalizable mm = (MyExternalizable)ois.readObject();
        mm.toString();
        System.out.println(mm.toString());
    } 
    catch (ClassNotFoundException ex) 
    {
        Logger.getLogger(MyExternalizable.class.getName()).log(Level.SEVERE, null, ex);
    }
    catch(IOException ex)
    {
        Logger.getLogger(MyExternalizable.class.getName()).log(Level.SEVERE, null, ex);
    }
}
}

ici si vous commentez le constructeur par défaut alors le code jettera l'exception ci-dessous:

 java.io.InvalidClassException: javaserialization.MyExternalizable;     
 javaserialization.MyExternalizable; no valid constructor.

nous pouvons observer que le mot de passe est une information sensible, donc je ne suis pas en train de la sérialiser dans la méthode écrite externe(ObjectOutput oo) et de ne pas fixer la valeur de same dans readExternal(ObjectInput oi). C'est la flexibilité qui est fournie par Externalisable.

la sortie du code ci-dessus est comme ci-dessous:

userName: nikki  passWord: student001  roll: 20
***********************************************************************
userName: nikki  passWord: null  roll: 20

nous pouvons observer que nous ne définissons pas la valeur du mot de passe donc il est nul.

la même chose peut être réalisée en déclarant le champ password comme transitoire.

private transient String passWord;

J'espère que ça aidera. Je m'excuse si j'ai fait des erreurs. Grâce.

32
répondu Trying 2017-12-28 08:52:28

juste pour être complet, le mot-clé transient comble également l'écart entre les deux.

si vous ne voulez sérialiser qu'une partie de votre objet, définissez simplement des champs spécifiques comme transient , en indiquant qu'ils ne doivent pas persister, et implémentez Serializable .

24
répondu Benjamin Wootton 2013-09-12 10:22:15

Sérialisation utilise certains comportements par défaut pour stocker et plus tard recréer l'objet. Vous pouvez spécifier dans quel ordre ou comment gérer les références et les structures de données complexes, mais finalement cela revient à utiliser le comportement par défaut pour chaque champ de données primitif.

externalisation est utilisé dans les rares cas où vous voulez vraiment stocker et reconstruire votre objet d'une manière complètement différente et sans utiliser les mécanismes de sérialisation par défaut pour les données Fields. Par exemple, imaginez que vous ayez votre propre schéma d'encodage et de compression unique.

19
répondu Uri 2009-05-03 20:12:54

principales différences entre Serializable et Externalizable

  1. interface marqueur : Serializable est interface marqueur sans aucune méthode. Externalizable interface contient deux méthodes: writeExternal() et readExternal() .
  2. processus de sérialisation : le processus de sérialisation par défaut sera activé pour les classes implémentant l'interface Serializable . Programmeur défini Le processus de sérialisation sera activé pour les classes implémentant l'interface Externalizable .
  3. Maintenance : Modifications incompatibles peut rompre la sérialisation.
  4. Backward Compatibility and Control : si vous devez prendre en charge plusieurs versions, vous pouvez avoir le plein contrôle avec Externalizable interface. Vous pouvez prendre en charge différentes versions de votre objet. Si vous mettez en œuvre Externalizable , il est de votre responsabilité de sérialiser super classe
  5. public Non-arg constructeur : Serializable utilise la réflexion pour construire l'objet et ne nécessite pas d'arg constructeur. Mais Externalizable exige public no-arg constructeur.

Consultez blog par Hitesh Garg pour plus de détails.

19
répondu Ravindra babu 2017-09-15 16:21:00

Sérialisation d'un Objet utilise le Serializable et Externalizable interfaces. Un objet Java n'est que sérialisable. si une classe ou l'une de ses superclasses implémente le java.io.L'interface sérialisable ou sa sous-interface, java.io.Externalisable. la plupart de la classe java sont sérialisables .

  • NotSerializableException : packageName.ClassName " pour participer à un objet de classe dans le processus de sérialisation, la classe doit implémenter soit L'interface sérialisable ou Externalisable.

enter image description here


Interface Sérialisable

Sérialisation d'un Objet produit un flux de données avec des informations sur les classes Java pour les objets qui sont être sauvé. Pour les objets sérialisables, suffisamment d'informations sont conservées pour restaurer ces objets même si une version différente (mais compatible) de l'implémentation de la classe est présente. L'interface Serialisable est définie pour identifier les classes qui implémentent le protocole serialisable:

package java.io;

public interface Serializable {};
  • l'interface de sérialisation n'a pas de méthodes ou de champs et sert seulement à identifier la sémantique d'être sérialisable. Pour sérialiser/désérialiser une classe, soit nous pouvons utiliser les méthodes writeObject et readObject par défaut (ou) nous pouvons modifier les méthodes writeObject et readObject d'une classe.
  • JVM aura le contrôle complet en sérialisant l'objet. utilisez mot-clé transitoire pour empêcher le membre de données d'être sérialisé.
  • ici les objets sérialisables sont reconstruits directement à partir du flux sans exécution
  • InvalidClassException " dans le processus de désérialisation, si la classe locale serialVersionUID valeur est différente de la classe correspondante de l'expéditeur. alors le résultat est en conflit java.io.InvalidClassException: com.github.objects.User; local class incompatible: stream classdesc serialVersionUID = 5081877, local class serialVersionUID = 50818771
  • les valeurs des champs non-transitoires et non-statiques de la classe sont sérialisées.

Interface Externalisable

Pour Externalizable d'objets, que l'identité de la classe de l'objet est enregistré par le conteneur; la classe doit sauvegarder et restaurer le contenu. L'interface Externalisable est définie comme suit:

package java.io;

public interface Externalizable extends Serializable
{
    public void writeExternal(ObjectOutput out)
        throws IOException;

    public void readExternal(ObjectInput in)
        throws IOException, java.lang.ClassNotFoundException;
}
  • l'interface Externalisable a deux méthodes, un objet externalisable doit mettre en œuvre des méthodes writeExternal et readExternal pour sauver/restaurer l'état d'un objet.
  • Programmeur doit prendre soin des objets à sérialiser. Comme un programmeur s'occupe de la sérialisation Donc, ici le mot-clé transitoire ne restreindra aucun objet dans le processus de sérialisation.
  • Lorsqu'un objet Externalisable est reconstruit, une instance est créée en utilisant le constructeur public no-arg, puis la méthode readExternal appelée. Les objets sérialisables sont restaurés en les lisant à partir D'une chaîne ObjectInputStream.
  • OptionalDataException "les champs doivent être dans le même ordre et taper comme nous les avons écrits. S'il ya une inadéquation de type de la rivière il jette OptionalDataException.

    @Override public void writeExternal(ObjectOutput out) throws IOException {
        out.writeInt( id );
        out.writeUTF( role );
        out.writeObject(address);
    }
    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.id = in.readInt();
        this.address = (Address) in.readObject();
        this.role = in.readUTF();
    }
    
  • les champs d'instance de la classe qui a écrit (exposé) à ObjectOutput sont sérialisés.


Example implements Serialisable

class Role {
    String role;
}
class User extends Role implements Serializable {

    private static final long serialVersionUID = 5081877L;
    Integer id;
    Address address;

    public User() {
        System.out.println("Default Constructor get executed.");
    }
    public User( String role ) {
        this.role = role;
        System.out.println("Parametarised Constructor.");
    }
}

class Address implements Serializable {

    private static final long serialVersionUID = 5081877L;
    String country;
}

exemple instruments Externalisables

class User extends Role implements Externalizable {

    Integer id;
    Address address;
    // mandatory public no-arg constructor
    public User() {
        System.out.println("Default Constructor get executed.");
    }
    public User( String role ) {
        this.role = role;
        System.out.println("Parametarised Constructor.");
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeInt( id );
        out.writeUTF( role );
        out.writeObject(address);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        this.id = in.readInt();
        this.address = (Address) in.readObject();
        this.role = in.readUTF();
    }
}

exemple

public class CustomClass_Serialization {
    static String serFilename = "D:/serializable_CustomClass.ser";

    public static void main(String[] args) throws IOException {
        Address add = new Address();
        add.country = "IND";

        User obj = new User("SE");
        obj.id = 7;
        obj.address = add;

        // Serialization
        objects_serialize(obj, serFilename);
        objects_deserialize(obj, serFilename);

        // Externalization
        objects_WriteRead_External(obj, serFilename);
    }

    public static void objects_serialize( User obj, String serFilename ) throws IOException{
        FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );

        // java.io.NotSerializableException: com.github.objects.Address
        objectOut.writeObject( obj );
        objectOut.flush();
        objectOut.close();
        fos.close();

        System.out.println("Data Stored in to a file");
    }
    public static void objects_deserialize( User obj, String serFilename ) throws IOException{
        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

            User user = (User) readObject;
            System.out.format("Obj[Id:%d, Role:%s] \n", user.id, user.role);

            Address add = (Address) user.address;
            System.out.println("Inner Obj : "+ add.country );
            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void objects_WriteRead_External( User 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.
            User user = new User();

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

            user.readExternal(ois);

            System.out.format("Obj[Id:%d, Role:%s] \n", user.id, user.role);

            Address add = (Address) user.address;
            System.out.println("Inner Obj : "+ add.country );
            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

@voir

8
répondu Yash 2018-01-17 12:35:00

l'interface Externalisable n'a pas été réellement fournie pour optimiser la performance du processus de sérialisation! mais pour fournir des moyens de mettre en œuvre votre propre traitement personnalisé et d'offrir un contrôle complet sur le format et le contenu du flux pour un objet et ses super types!

exemples de ceci est l'implémentation de AMF (ActionScript Message Format) remoting pour transférer des objets natifs action script sur le réseau.

7
répondu Ali Joudeh 2012-08-27 08:37:01

https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html

serialization par défaut est quelque peu verbeux, et suppose le scénario d'utilisation le plus large possible de l'objet serialized, et en conséquence le format par défaut (Serializable) annote le flux résultant avec des informations sur la classe de l'objet serialized.

externalisation donner au producteur du flux d'objet complète contrôle des métadonnées précises de la classe (le cas échéant) au-delà de l'identification minimale requise de la classe (par exemple son nom). Cela est clairement souhaitable dans certaines situations, telles que les environnements fermés, où le producteur du flux d'objets et son consommateur (qui réifie l'objet du flux) sont appariés, et des métadonnées supplémentaires sur la classe ne servent à rien et dégradent les performances.

en outre (comme le souligne Uri) externalisation prévoit également contrôle de l'encodage des données dans le flux correspondant aux types Java. Pour (un contrived) exemple, vous pouvez souhaiter enregistrer booléen true comme ' Y 'et false comme'N'. L'externalisation vous permet de le faire.

7
répondu alphazero 2017-07-03 18:06:42

lorsque vous envisagez des options pour améliorer les performances, n'oubliez pas la sérialisation personnalisée. Vous pouvez laisser Java faire ce qu'il fait bien, ou au moins assez bien, gratuitement , et fournir un support personnalisé pour ce qu'il fait mal. C'est généralement beaucoup moins de code que le plein soutien Externalisable.

2
répondu Ed Staub 2011-10-28 13:47:42

il y a tellement de différences entre sérialisable et Externalisable mais quand nous comparons la différence entre custom Serialisable (overrided writeObject () & readObject ()) et Externalisable alors nous trouvons que l'implémentation custom est étroitement liée à la classe ObjectOutputStream où comme dans le cas Externalisable , nous fournissons une implémentation de ObjectOutput qui peut être la classe ObjectOutputStream ou il pourrait être un autre comme org.Apache.Mina.filtrer.codec.sérialisation.ObjectSerializationOutputStream

en cas d'interface Externalisable

@Override
public void writeExternal(ObjectOutput out) throws IOException {
    out.writeUTF(key);
    out.writeUTF(value);
    out.writeObject(emp);
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    this.key = in.readUTF();
    this.value = in.readUTF();
    this.emp = (Employee) in.readObject();
}





**In case of Serializable interface**


        /* 
             We can comment below two method and use default serialization process as well
             Sequence of class attributes in read and write methods MUST BE same.
        // below will not work it will not work . 
        // Exception = java.io.StreamCorruptedException: invalid type code: 00\
              private void writeObject(java.io.ObjectOutput stream) 
              */
            private void writeObject(java.io.ObjectOutputStream Outstream)
                    throws IOException {

                System.out.println("from writeObject()");
                /*     We can define custom validation or business rules inside read/write methods.
 This way our validation methods will be automatically 
    called by JVM, immediately after default serialization 
    and deserialization process 
    happens.
                 checkTestInfo();
                */

                stream.writeUTF(name);
                stream.writeInt(age);
                stream.writeObject(salary);
                stream.writeObject(address);
            }

            private void readObject(java.io.ObjectInputStream Instream)
                    throws IOException, ClassNotFoundException {
                System.out.println("from readObject()");
                name = (String) stream.readUTF();
                age = stream.readInt();
                salary = (BigDecimal) stream.readObject();
                address = (Address) stream.readObject();
                // validateTestInfo();
            }

j'ai ajouté un exemple de code pour mieux expliquer. veuillez vérifier dans/objet de cas de Externalizable. Ce ne sont pas lié à une mise en œuvre directement.

Où comme Outstream / Instream sont étroitement liés aux classes. Nous pouvons étendre ObjectOutputStream / ObjectInputStream mais il un peu difficile à utiliser.

2
répondu Ashish Sharma 2017-10-12 03:41:49

Sérialisation en Java

Java fournit un mécanisme appelé Object Serialization qui permet à l'utilisateur de stocker la structure d'un objet et des données dans un fichier externe. Ce fichier contient des informations reagarding objet, nature de l'objet, le type de membres et des données détenues par les membres.

interface Externalisable:

tout comme l'interface sérialisable, Externalisable stocke également un objet avec ses données à un fichier externe qui nous peut le récupérer plus tard. Mais il y a une certaine différence: Dans la sérialisation, tous les membres / variables de l'objet sont sérialisés dans le fichier externe, alors que dans L'externalisation, nous pouvons spécifiquement mentionner quels membres nous voulons ainsi être stockés. Puisque serialization serialize classe entière, nous n'avons pas besoin d'écrire des méthodes pour lire et écrire le fichier externe. Mais Externalisable nécessite deux méthodes, à savoir readExternal () et writeExternal ()

Complete Référence: différence entre sérialisation et externalisation

1
répondu Shadab Kazi 2018-09-13 12:47:24

fondamentalement, Serializable est une interface marqueur qui implique qu'une classe est sûre pour la sérialisation et la JVM détermine comment elle est sérialisée. Externalizable contient 2 méthodes, readExternal et writeExternal . Externalizable permet à l'exécuteur de décider comment un objet est sérialisé, où comme Serializable sérialise les objets de la manière par défaut.

0
répondu SirGoPythonJavaCppRuby the 3rd 2018-10-11 03:18:38