web-dev-qa-db-fra.com

Pourquoi générer un long serialVersionUID au lieu d'un simple 1L?

Lorsque la classe implémente Serializable dans Eclipse, j'ai deux options: ajouter le paramètre par défaut serialVersionUID(1L) ou le programme généré serialVersionUID(3567653491060394677L). Je pense que le premier est plus cool, mais j'ai souvent vu des gens utiliser la seconde option. Y at-il une raison pour générer long serialVersionUID?

203
IAdapter

Autant que je sache, ce ne serait que pour la compatibilité avec les versions précédentes. Cela ne serait utile que si vous avez négligé d'utiliser un serialVersionUID auparavant, puis apporté une modification dont vous savez qu'elle devrait être compatible mais qui entraîne la rupture de la sérialisation.

Voir le Spécification de sérialisation Java pour plus de détails.

85
Michael Myers

Le but de la version de sérialisation UID est de garder trace des différentes versions d'une classe afin d'effectuer une sérialisation valide des objets.

L'idée est de générer un identifiant unique pour une certaine version d'une classe, qui est ensuite modifié lorsque de nouveaux détails sont ajoutés à la classe, tels qu'un nouveau champ, ce qui affecterait la structure de l'objet sérialisé.

Toujours en utilisant le même identifiant, tel que 1L signifie que, dans le futur, si la définition de classe est modifiée, ce qui entraîne des modifications dans la structure de l'objet sérialisé, il y aura de fortes chances que des problèmes se produisent lors de la tentative de désérialisation d'un objet.

Si l'ID est omis, Java calculera l'ID pour vous en fonction des champs de l'objet, mais je pense que le processus est coûteux. Par conséquent, en fournir un manuellement améliorera les performances.

Voici quelques liens vers des articles traitant de la sérialisation et du contrôle de version des classes:

69
coobird

La principale raison de la génération générée serait de la rendre compatible avec une version existante de la classe ayant déjà des copies persistantes.

18
Robin

Le "long" défaut de serialVersionUID est la valeur par défaut telle que définie par le spécification de sérialisation Java , calculée à partir du comportement de sérialisation par défaut.

Donc, si vous ajoutez le numéro de version par défaut, votre classe sera (dés) sérialisée plus rapidement tant que rien n'a changé structurellement, mais vous devrez veiller à ce que si vous changez la classe (ajout/suppression de champs) numéro de série.

Si vous ne devez pas être compatible avec les flux de bits existants, vous pouvez simplement mettre 1L là et incrémente la version selon les besoins en cas de changement. C'est-à-dire que lorsque la version de sérialisation par défaut de la classe modifiée serait différente de la version par défaut de l'ancienne classe.

14
David Schmitt

Vous devez absolument créer un serialVersionUID chaque fois que vous définissez une classe qui implémente Java.io.Serializable. Si vous ne le faites pas, on en créera un automatiquement, mais c'est mauvais. Le serialVersionUID généré automatiquement est basé sur les signatures de méthode de votre classe. Par conséquent, si vous modifiez votre classe par la suite pour ajouter une méthode (par exemple), la désérialisation des "anciennes" versions de la classe échouera. Voici ce qui peut arriver:

  1. Créez la première version de votre classe sans définir le serialVersionUID.
  2. Sérialiser une instance de votre classe dans un magasin persistant; Un serialVersionUID est automatiquement généré pour vous.
  3. Modifiez votre classe pour ajouter une nouvelle méthode et redéployez votre application.
  4. Essayez de désérialiser l'instance qui a été sérialisée à l'étape 2, mais elle échoue à présent (dans les cas où elle devrait aboutir), car elle a un autre serialVersionUID généré automatiquement.
10
Pankaj Kumar

Si vous ne spécifiez pas un serialVersionUID, alors Java en crée un à la volée. Le serialVersionUID généré est ce nombre. Si vous modifiez quelque chose dans votre classe qui ne rend pas votre classe incompatible avec les précédents Si le verge est sérialisé mais que le hachage est modifié, vous devez utiliser le numéro de série très grand numéro générique (ou le nombre "attendu" du message d'erreur). Sinon, si vous surveillez vous-même tout, 0, 1, 2. .. est mieux.

6
joeforker

Lorsque vous utilisez serialVersionUID (1L) plutôt que de générer serialVersionUID (3567653491060394677L), vous dites quelque chose.

Vous dites que vous êtes à 100% sûr qu'aucun système qui touchera jamais cette classe ne possède une version sérialisée incompatible de cette classe avec un numéro de version de 1.

Si vous pouvez imaginer une excuse quelconque pour ne pas connaître l'historique des versions sérialisées, cela peut être difficile à dire en toute confiance. Au cours de sa vie, de nombreuses personnes maintiendront un cours réussi, vivront dans de nombreux projets et résideront dans de nombreux systèmes.

Vous pouvez agoniser pour ça. Ou vous pouvez jouer à la loterie en espérant perdre. Si vous générez la version, vous avez une infime chance que tout se passe mal. Si vous supposez "Hey, je parie que personne n'a encore utilisé 1", vos chances sont plus grandes que minuscules. C'est précisément parce que nous pensons tous que 0 et 1 sont cool que vous avez plus de chances de les toucher.

-

Lorsque vous générez serialVersionUID (3567653491060394677L) au lieu d'utiliser serialVersionUID (1L), vous dites quelque chose.

Vous dites que des personnes ont peut-être créé ou généré manuellement d'autres numéros de version au cours de l'historique de cette classe et vous ne vous inquiétez pas, car les Longs génèrent des nombres énormes.

De toute façon, à moins de connaître parfaitement l’historique des numéros de version utilisés lors de la sérialisation de la classe dans l’univers entier de son emplacement actuel ou futur, vous tentez votre chance. Si vous avez le temps de vous assurer à 100% que 1 est AOK, allez-y. Si cela vous demande trop de travail, générez le nombre à l’aveuglette. Vous avez plus de chances de gagner à la loterie que de faire une erreur. Si c'est le cas, faites le moi savoir et je vous achèterai une bière.

En parlant de jouer à la loterie, je vous ai peut-être donné l’impression que serialVersionUID est généré de manière aléatoire. En fait, tant que la plage de nombres est répartie de manière égale sur toutes les valeurs possibles d'un Long, tout va bien. Cependant, cela se fait réellement de cette façon:

http://docs.Oracle.com/javase/6/docs/platform/serialization/spec/class.html#41

La seule différence que vous obtenez avec cela est que vous n'avez pas besoin d'une source aléatoire. Vous utilisez les changements dans la classe elle-même pour changer le résultat. Mais selon le principe des casiers, il y a encore une chance que cela risque de mal tourner et d'avoir une collision. C'est juste incroyablement improbable. Alors bonne chance pour me prendre une bière.

Cependant, même si la classe ne vivra jamais que dans un système et une base de code, penser que incrémenter le nombre manuellement ne vous laisse aucune chance de collision signifie simplement que vous ne comprenez pas les humains. :)

4
SomeGuy

SerialVersionUID est une exception à la règle selon laquelle "les champs statiques ne sont pas sérialisés". ObjectOutputStream écrit chaque fois la valeur de serialVersionUID dans le flux de sortie. ObjectInputStream le relit et si la valeur lue dans le flux ne correspond pas à la valeur serialVersionUID de la version actuelle de la classe, elle lève l'exception InvalidClassException. De plus, s'il n'y a pas de serialVersionUID officiellement déclaré dans la classe à sérialiser, le compilateur l'ajoute automatiquement avec une valeur générée en fonction des champs déclarés dans la classe.

1
Lucky

Parce que dans de nombreux cas, l'id par défaut n'est pas unique. Nous créons donc un identifiant pour créer un concept unique.

0
Pushpendra Kuntal

Pour ajouter à la réponse de @David Schmitts, en règle générale, j'utiliserais toujours le défaut par défaut 1L. J'ai seulement eu à revenir en arrière et à en changer quelques-unes à quelques reprises, mais je le savais quand j'ai fait la modification et mis à jour le numéro par défaut d'une unité à chaque fois.

Dans mon entreprise actuelle, ils ont besoin du numéro généré automatiquement. Je l'utilise donc comme convention, mais je préfère le numéro par défaut. Ma conception est que, si ce n’est pas une convention où vous travaillez, utilisez la valeur par défaut, à moins que vous ne pensiez changer constamment la structure de vos classes sérialisées pour une raison quelconque.

0
James Drinkard