55 votes

Quand dois-je modifier le serialVersionUID ?

Je sais que je peux utiliser serialVersionUID pour contrôler la version des classes. Et j'ai lu que je peux ensuite ajouter ou supprimer des champs et que la classe sera toujours compatible, elle utilisera simplement les valeurs par défaut.

Lorsque doit Je change le serialVersionUID ?

0 votes

55voto

Vineet Reynolds Points 40529

La valeur du champ serialVersionUID doit idéalement être modifiée lorsque des modifications incompatibles sont apportées à la structure de la classe. La liste complète des modifications incompatibles est présente dans le Spécification de sérialisation des objets Java .

Pour aller plus loin, les modifications incompatibles apportées à une classe empêcheront le mécanisme de désérialisation de créer une instance de l'objet, car le flux contient des informations qui ne correspondent pas à la définition actuelle de la classe.

1 votes

Non, ce n'est pas le cas. Les modifications incompatibles énumérées dans la spécification sont celles qui entraîneront des exceptions si elles sont tentées. Celles qui ne correspondent pas à la définition de la classe actuelle sont les suivantes compatible et la liste de ces changements est longue.

2 votes

Pour aller plus loin, des modifications incompatibles [...] empêchent le mécanisme de désérialisation de créer une instance : Est-ce que cette réponse ne revient pas à dire que je devrais changer serialVersionUID pour faire en sorte que le mécanisme de désérialisation lève une exception, même s'il peut déjà le faire sans mon aide car il s'agit d'une modification incompatible qui empêche ledit mécanisme de fonctionner ? Si c'est le cas, je pense qu'il devrait y avoir une clarification sur la façon dont cela est utile. (J'ai des doutes ici car La réponse d'EJP a beaucoup plus de sens).

28voto

EJP Points 113412

Le mantra fréquemment répété sur le fait de changer le serialVersionUID à chaque fois que vous changez de classe est une absurdité complète et totale. Voir cet article du Sun qu'ils ont republié sur leur site et qui a été migré vers le réseau Oracle Technology Network après l'acquisition.

Vous devez modifier le serialVersionUID sólo lorsque vous voulez délibérément rompre la compatibilité avec toutes les sérialisations existantes, ou lorsque vos modifications de la classe sont si radicales que vous n'avez pas le choix - dans ce cas, vous devriez vraiment réfléchir plusieurs fois à ce que vous faites réellement.

Dans tous les autres cas, vous devriez faire sauter votre chaudière en essayant d'utiliser les fonctions personnalisées de l'application readObject()/writeObject() et/ou writeReplace()/readResolve() méthodes et/ou serialFields afin que vous puissiez continuer à lire des objets à partir de ces sérialisations existantes. Une fois que vous avez brisé cela, vous allez au devant d'un grand mal de tête, voire d'un cauchemar.

1 votes

Cette réponse pourrait être améliorée en indiquant exactement ce avec quoi vous n'êtes pas d'accord, ou ce que vous pensez que l'article en question défend. En lisant l'article, je ne vois pas ce avec quoi Sun est en "désaccord".

1 votes

Et si j'ajoutais un nouveau champ à une classe. Cette modification est toujours compatible : aucune exception ne sera levée. Mais le champ ne contiendra aucune information, donc sémantiquement c'est incompatible. Dois-je augmenter l'UID dans ce cas ?

2 votes

@damluar Non. Cela va seulement le rendre plus incompatible. Au moins, si vous ne provoquez pas l'exception, vous avez plusieurs possibilités de réparer la sémantique. Avec l'exception, vous n'avez aucun espoir.

6voto

Tom G Points 5727

Si vous ne spécifiez pas un serialVersionUID dans votre Serializable le compilateur Java en spécifiera un pour vous - il s'agit essentiellement d'un hachage du nom de la classe, des noms d'interface, des méthodes et des champs de la classe. Les méthodes peuvent être modifiées à tout moment. Ainsi, si vous souhaitez modifier la façon dont une classe stockée est désérialisée, vous pouvez remplacer la méthode readObject. Si vous spécifiez l'option serialVersionUID dans votre code, le compilateur ne le remplacera pas, même si vous effectuez des modifications incompatibles, ce qui peut entraîner une erreur de compilation. exception au moment de l'exécution -- votre IDE ou votre compilateur ne vous donnera pas d'avertissement. (EDIT -- merci EJP) Les IDE tels qu'Eclipse peuvent insérer l'UID du compilateur pour vous, si vous voulez vérifier facilement comment le compilateur voit certaines modifications.

Si vous effectuez souvent des modifications, conservez une ancienne version du fichier disque pour tester la désérialisation. Vous pouvez écrire des tests unitaires pour essayer de lire l'ancien fichier, et voir si cela fonctionne ou si c'est totalement incompatible.

Une mise en garde, j'ai personnellement fait l'expérience de la douleur que représente le fait de travailler avec Serializable des classes destinées à l'origine à un stockage à long terme qui ont été mal conçues. Par exemple, le stockage des éléments de l'interface graphique sur le disque plutôt que leur création en cas de besoin. Demandez-vous si Serializable est vraiment le meilleur moyen de sauvegarder vos données.

0 votes

+1 pour avoir attiré l'attention sur les problèmes que pose Serializable pour le stockage des données, surtout lorsque vous utilisez vos propres classes (celles du JDK lui-même sont au moins assez stables).

0 votes

... des changements incompatibles, qui peuvent entraîner des exceptions au moment de l'exécution" - vous devez clarifier cela. Vous obtenez des IOExceptions, pas des RuntimeExceptions.

0 votes

@EJP Vous avez raison, j'aurais pu mieux le formuler. Vous obtiendrez une exception IOEXception /au moment de l'exécution/, c'est ce que je voulais indiquer par là - votre IDE ou votre compilateur ne vous préviendra pas à l'avance.

4voto

Malt Points 4082

Dans un souci d'exhaustivité, voici une liste des modifications qui rompent la compatibilité de la sérialisation Java selon la norme spécification java 8 :

  • Suppression de champs
  • Déplacement des classes vers le haut ou le bas de la hiérarchie
  • Changer un champ non statique en champ statique ou un champ non transitoire en champ transitoire
  • Modification du type déclaré d'un champ primitif
  • Modifier la méthode writeObject ou readObject pour qu'elle n'écrive ou ne lise plus les données du champ par défaut ou la modifier pour qu'elle tente de les écrire ou de les lire alors que la version précédente ne le faisait pas.
  • Changement d'une classe de Serializable à Externalizable ou vice versa
  • Modification d'une classe d'un type non enum à un type enum ou vice versa
  • Suppression de Serializable ou Externalizable
  • Ajout de la méthode writeReplace ou readResolve à une classe

0voto

Thien Diep Points 1

Pour déclarer votre propre serialVersionUID en java, tapez ceci dans le fichier classe d'objets sérialisés :

@Serial

private static final long serialVersionUID = desired_number ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X