java c'est generator - Qu'est-ce qu'un serialVersionUID et pourquoi devrais-je l'utiliser?





10 Answers

Si vous sérialisez simplement parce que vous devez sérialiser pour l'implémentation (qui se soucie de savoir si vous sérialisez une session HTTPS, par exemple ... si elle est stockée ou non, vous ne vous inquiétez probablement pas de la désérialisation d'un objet de formulaire) , alors vous pouvez l'ignorer.

Si vous utilisez réellement la sérialisation, le fait de stocker et de récupérer des objets directement à l'aide de la sérialisation n'a plus d'importance. SerialVersionUID représente la version de votre classe. Vous devez l'incrémenter si la version actuelle de votre classe n'est pas rétrocompatible avec sa version précédente.

La plupart du temps, vous n'utiliserez probablement pas directement la sérialisation. Si tel est le cas, générez un ID utilisateur sérialisable par défaut en cliquant sur l'option de réparation rapide et ne vous inquiétez pas.

1l use serialisation

Eclipse émet des avertissements lorsqu'un serialVersionUID est manquant.

La classe sérialisable Foo ne déclare pas un champ final serialVersionUID statique de type long

Qu'est-ce que serialVersionUID et pourquoi est-ce important? Veuillez montrer un exemple où l'absence de serialVersionUID un problème.




Vous pouvez dire à Eclipse d'ignorer ces avertissements serialVersionUID:

Fenêtre> Préférences> Java> Compilateur> Erreurs / Avertissements> Problèmes de programmation potentiels

Au cas où vous ne le sauriez pas, il y a beaucoup d'autres avertissements que vous pouvez activer dans cette section (ou même en signaler quelques-uns comme des erreurs), beaucoup sont très utiles:

  • Problèmes de programmation potentiels: affectation booléenne accidentelle possible
  • Problèmes de programmation potentiels: Accès nul au pointeur
  • Code inutile: la variable locale n'est jamais lue
  • Code inutile: contrôle nul redondant
  • Code inutile: transtypage inutile ou 'instanceof'

et beaucoup plus.




Qu'est-ce qu'un serialVersionUID et pourquoi devrais-je l'utiliser?

SerialVersionUID est un identifiant unique pour chaque classe. JVM utilise pour comparer les versions de la classe en s'assurant que la même classe a été utilisée lors de la sérialisation chargée lors de la désérialisation.

La spécification d'un donne plus de contrôle, bien que JVM en génère un si vous ne le spécifiez pas. La valeur générée peut différer entre différents compilateurs. De plus, parfois, vous souhaitez simplement, pour une raison quelconque, interdire la désérialisation d'anciens objets sérialisés [ backward incompatibility ], et dans ce cas, vous devez simplement modifier le paramètre serialVersionUID.

Les javadocs pour Serializable disent :

Le calcul série serialVersionUID par défaut est très sensible aux détails de classe qui peuvent varier en fonction de l'implémentation du compilateur et peut donc entraîner des InvalidClassException inattendues lors de la désérialisation.

Par conséquent, vous devez déclarer serialVersionUID car cela nous donne plus de contrôle .

Cet article a quelques bons points sur le sujet.




Si vous obtenez cet avertissement sur une classe pour laquelle vous ne pensez jamais à la sérialisation et que vous ne vous êtes pas déclarée implements Serializable , c'est souvent parce que vous avez hérité d'une super-classe, qui implémente Serializable. Souvent, il serait préférable de déléguer à un tel objet plutôt que d'utiliser l'héritage.

Donc, au lieu de

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

faire

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

et dans les méthodes appropriées, appelez myList.foo() au lieu de this.foo() (ou super.foo() ). (Cela ne convient pas dans tous les cas, mais encore assez souvent.)

Je vois souvent des personnes rallonger JFrame ou autres, alors qu’elles n’ont qu’à déléguer à cela. (Cela aide également pour l'auto-complétion dans un IDE, car JFrame a des centaines de méthodes, dont vous n'avez pas besoin lorsque vous souhaitez appeler vos méthodes personnalisées dans votre classe.)

Dans certains cas, l'avertissement (ou le serialVersionUID) est inévitable lorsque vous étendez à partir de AbstractAction, généralement dans une classe anonyme, en ajoutant uniquement la méthode actionPerformed. Je pense qu'il ne devrait pas y avoir d'avertissement dans ce cas (puisque normalement vous ne pouvez pas sérieusement sérialiser et désérialiser de telles classes anonymes sur différentes versions de votre classe), mais je ne sais pas comment le compilateur pourrait le reconnaître.




Pour comprendre la signification du champ serialVersionUID, il convient de comprendre le fonctionnement de la sérialisation / désérialisation.

Lorsqu'un objet de classe Serializable est sérialisé, Java Runtime associe un numéro de version série (appelé en tant que serialVersionUID) à cet objet sérialisé. Au moment où vous désérialisez cet objet sérialisé, Java Runtime fait correspondre le serialVersionUID de l'objet sérialisé avec le serialVersionUID de la classe. Si les deux sont égaux, alors seul le processus de désérialisation supplémentaire est lancé, sinon l'instruction InvalidClassException est levée.

Nous concluons donc que pour que le processus de sérialisation / désérialisation aboutisse, le serialVersionUID de l'objet sérialisé doit être équivalent au serialVersionUID de la classe. Si le programmeur spécifie explicitement la valeur serialVersionUID dans le programme, la même valeur sera associée à l’objet sérialisé et à la classe, quelle que soit la plate-forme de sérialisation et de désérialisation (par exemple, la sérialisation peut être effectuée sur une plate-forme telle que windows en utilisant sun ou MS JVM et Deserialization peuvent se trouver sur différentes plateformes Linux utilisant Zing JVM).

Mais si le programme ne spécifie pas serialVersionUID, alors que Serialization \ DeSerialization n’importe quel objet, le moteur d’exécution Java utilise son propre algorithme pour le calculer. Cet algorithme de calcul serialVersionUID varie d'un JRE à un autre. Il est également possible que l'environnement dans lequel l'objet est sérialisé utilise un seul JRE (ex: SUN JVM) et que l'environnement dans lequel la désérialisation se produit utilise Linux Jvm (zing). Dans de tels cas, serialVersionUID associé à un objet sérialisé sera différent de serialVersionUID de la classe calculée dans l'environnement de désérialisation. À son tour, la désérialisation ne sera pas réussie. Donc, pour éviter de telles situations / problèmes, le programmeur doit toujours spécifier serialVersionUID de la classe Serializable.




En ce qui concerne un exemple où le serialVersionUID manquant peut causer un problème:

Je travaille sur cette application Java EE composée d'un module Web utilisant un module EJB . Le module Web appelle le module EJB distance et transmet un POJO qui implémente Serializable en tant qu'argument.

POJO's classe de ce POJO's était empaquetée dans le fichier jar EJB et dans son propre fichier jar dans le module WEB-INF / lib du module Web. Ils appartiennent en fait à la même classe, mais lorsque je compresse le module EJB, je décompresse le fichier jar de ce POJO pour l’emballer avec le module EJB.

L'appel à l' EJB échouait avec l'exception ci-dessous car je n'avais pas déclaré son serialVersionUID :

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52



Les données de champ représentent certaines informations stockées dans la classe. Class implémente l'interface Serializable , eclipse a donc automatiquement proposé de déclarer le champ serialVersionUID . Commençons par la valeur 1 définie ici.

Si vous ne voulez pas que cet avertissement vienne, utilisez ceci:

@SuppressWarnings("serial")



Il serait bien que CheckStyle puisse vérifier que le serialVersionUID d’une classe qui implémente Serializable a une bonne valeur, c’est-à-dire qu’il correspond à ce que le générateur d’identificateurs de version série produirait. Par exemple, si vous avez un projet avec de nombreux DTO sérialisables, n'oubliez pas de supprimer le serialVersionUID existant et de le régénérer est une tâche ardue. À l'heure actuelle, le seul moyen (à ma connaissance) de le vérifier est de régénérer chaque classe et de le comparer. le vieux. C'est très très douloureux.




Pourquoi utiliser SerialVersionUIDinside Serializableclass en Java?

Au cours de serializationl'exécution, Java crée un numéro de version pour une classe, afin de pouvoir la désérialiser ultérieurement. Ce numéro de version est connu sous le nom SerialVersionUIDde Java.

SerialVersionUIDest utilisé pour la version des données sérialisées. Vous ne pouvez désérialiser une classe que si elle SerialVersionUIDcorrespond à l'instance sérialisée. Lorsque nous ne déclarons pas SerialVersionUIDdans notre classe, le runtime Java le génère pour nous mais ce n'est pas recommandé. Il est recommandé de déclarer SerialVersionUIDcomme private static final longvariable pour éviter le mécanisme par défaut.

Lorsque vous déclarez une classe Serializableen implémentant une interface de marqueur java.io.Serializable, l'exécution Java de l'instance de cette classe est conservée sur le disque à l'aide du mécanisme de sérialisation par défaut, à condition que vous n'ayez pas personnalisé le processus à l'aide de l' Externalizableinterface.

voir aussi Pourquoi utiliser SerialVersionUID dans la classe Serializable en Java

Code: javassist.SerialVersionUID




Cette question est très bien documentée dans Effective Java de Joshua Bloch. Un très bon livre et à lire absolument. Je vais exposer certaines des raisons ci-dessous:

Le runtime de sérialisation fournit un numéro appelé Version série pour chaque classe sérialisable. Ce numéro s'appelle serialVersionUID. Il y a maintenant un peu de math derrière ce nombre et il est basé sur les champs / méthodes définis dans la classe. Pour la même classe, la même version est générée à chaque fois. Ce numéro est utilisé lors de la désérialisation pour vérifier que l'expéditeur et le destinataire d'un objet sérialisé ont des classes chargées pour cet objet compatibles avec la sérialisation. Si le destinataire a chargé une classe pour l'objet dont l'ID de série est différent de celui de la classe de l'expéditeur correspondante, la désérialisation entraîne une exception InvalidClassException.

Si la classe est sérialisable, vous pouvez également déclarer explicitement votre propre serialVersionUID en déclarant un champ nommé "serialVersionUID" qui doit être statique, final et de type long. La plupart des IDE comme Eclipse vous aident à générer cette longue chaîne.




Related