Lorsque la classe implémente Serializable dans Eclipse, j'ai deux options: ajouter par défaut serialVersionUID(1L)
ou généré serialVersionUID(3567653491060394677L)
. Je pense que la première est plus cool, mais plusieurs fois j'ai vu des gens utiliser la deuxième option. Y a-t-il une raison de générer long serialVersionUID
?
210
0L
qu'au début.Réponses:
Pour autant que je sache, ce serait uniquement pour des raisons de compatibilité avec les versions précédentes. Cela ne serait utile que si vous avez négligé d'utiliser un serialVersionUID auparavant, puis effectué une modification que vous savez être compatible, mais qui provoque la rupture de la sérialisation.
Voir la spécification de sérialisation Java pour plus de détails.
la source
Le but de la version de sérialisation UID est de garder une 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 ID unique à une certaine version d'une classe, qui est ensuite modifié lorsque de nouveaux détails sont ajoutés à la classe, comme un nouveau champ, ce qui affecterait la structure de l'objet sérialisé.
Toujours en utilisant le même ID, ce qui
1L
signifie qu'à l'avenir, si la définition de classe est modifiée, ce qui entraîne des modifications de la structure de l'objet sérialisé, il y a de fortes chances que des problèmes surviennent lors de la tentative de désérialisation d'un objet.Si l'ID est omis, Java calculera réellement l'ID pour vous en fonction des champs de l'objet, mais je pense que c'est un processus coûteux, donc en fournir un manuellement améliorera les performances.
Voici quelques liens vers des articles qui traitent de la sérialisation et du versionnement des classes:
la source
Note - It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.
Le commentaire ci-dessus a été tiré de la spécification Java Object Serialization Specification version 6.0La principale raison de la génération serait de la rendre compatible avec une version existante de la classe qui a déjà des copies persistantes.
la source
La valeur par défaut "longue" de
serialVersionUID
est la valeur par défaut définie par la 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 (dé-) sérialise plus rapidement tant que rien n'a structurellement changé, mais vous devrez vous assurer que si vous changez la classe (ajouter / supprimer des champs), vous mettrez également à jour le numéro de série.
Si vous n'avez pas besoin d'être compatible avec les flux binaires existants, vous pouvez simplement
1L
y mettre et incrémenter la version selon les besoins lorsque quelque chose change. Autrement dit, 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.la source
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, un sera créé automatiquement pour vous, mais c'est mauvais. Le serialVersionUID généré automatiquement est basé sur les signatures de méthode de votre classe, donc si vous changez votre classe à l'avenir pour ajouter une méthode (par exemple), la désérialisation des "anciennes" versions de la classe échouera. Voici ce qui peut arriver:la source
Si vous ne spécifiez pas un serialVersionUID, Java en crée un à la volée. Le serialVersionUID généré est ce numéro. Si vous changez quelque chose dans votre classe qui ne rend pas vraiment votre classe incompatible avec les versions précédentes sérialisées mais modifie le hachage, alors vous devez utiliser le serialVersionUID généré en très grand nombre (ou le numéro "attendu" du message d'erreur) . Sinon, si vous suivez tout vous-même, 0, 1, 2 ... c'est mieux.
la source
Lorsque vous utilisez serialVersionUID (1L) plutôt que de générer serialVersionUID (3567653491060394677L), vous dites quelque chose.
Vous dites que vous êtes sûr à 100% qu'aucun système ne touchera jamais cette classe qui a une version sérialisée incompatible de cette classe avec un numéro de version de 1.
Si vous pouvez penser à une excuse pour que l'historique de sa version sérialisée soit inconnu, cela pourrait être difficile à dire avec confiance. Au cours de sa vie, un cours réussi sera maintenu par de nombreuses personnes, vivra dans de nombreux projets et résidera dans de nombreux systèmes.
Vous pouvez agoniser à ce sujet. Ou vous pouvez jouer à la loterie en espérant perdre. Si vous générez la version, vous avez une petite chance que les choses tournent mal. Si vous supposez "Hé, je parie que personne n'en 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) plutôt que d'utiliser serialVersionUID (1L), vous dites quelque chose.
Vous dites que les gens peuvent avoir créé ou généré manuellement d'autres numéros de version au cours de l'histoire de cette classe et cela ne vous dérange pas parce que les Longs font flipper de gros nombres.
Quoi qu'il en soit, à moins que vous ne connaissiez parfaitement l'historique des numéros de version utilisés lors de la sérialisation de la classe dans l'univers entier de l'endroit où elle a existé ou existera, vous tentez. Si vous avez le temps de vous assurer à 100% que 1 est AOK, allez-y. Si c'est trop de travail, allez-y et générez aveuglément le nombre. Vous avez plus de chances de gagner à la loterie que de vous tromper. Si c'est le cas, faites-le moi savoir et je vous achèterai une bière.
Avec toutes ces discussions sur 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 uniformément sur toutes les valeurs possibles d'un Long, ce serait bien. Cependant, cela se fait de cette façon:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
La seule différence que vous obtenez avec cela est que vous n'avez pas besoin d'une source de hasard. Vous utilisez les changements dans la classe elle-même pour changer le résultat. Mais selon le principe du pigeonhole, il y a encore une chance qu'il puisse mal tourner et avoir une collision. C'est incroyablement improbable. Alors bonne chance pour avoir une bière de moi.
Cependant, même si la classe ne vivra que dans un seul système et une seule base de code, penser qu'incrémenter le nombre à la main vous donne zéro chance de collision signifie simplement que vous ne comprenez pas les humains. :)
la source
Eh bien, 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 dans la version actuelle de la classe, il 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.
la source
Parce que dans de nombreux cas, l'ID par défaut n'est pas unique. nous créons donc id pour faire un concept unique.
la source
Pour ajouter à la réponse de @David Schmitts, en règle générale, j'utiliserais toujours le 1 L par défaut par convention. Je n'ai eu qu'à revenir en arrière et à changer certains d'entre eux quelques fois, mais je le savais quand j'ai fait le changement et mis à jour le numéro par défaut d'un à chaque fois.
Dans ma société actuelle, ils ont besoin du numéro généré automatiquement, donc je l'utilise pour la convention, mais je préfère la valeur par défaut. Mon avis est, si ce n'est pas une convention où vous travaillez, utilisez la valeur par défaut, à moins que vous pensiez que vous changerez constamment la structure de vos classes sérialisées pour une raison quelconque.
la source
Le but de la version de sérialisation UID est de garder une 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 ID unique à une certaine version d'une classe, qui est ensuite modifié lorsque de nouveaux détails sont ajoutés à la classe, comme un nouveau champ, ce qui affecterait la structure de l'objet sérialisé.
Une explication simple:
Êtes-vous en train de sérialiser des données?
La sérialisation consiste essentiellement à écrire des données de classe dans un fichier / flux / etc. La désérialisation consiste à lire ces données dans une classe.
Comptez-vous entrer en production?
Si vous testez simplement quelque chose avec des données non importantes / fausses, ne vous en faites pas (sauf si vous testez directement la sérialisation).
Est-ce la première version?
Si tel est le cas, définissez serialVersionUID = 1L.
S'agit-il de la deuxième, troisième, etc. version prod?
Maintenant, vous devez vous soucier de serialVersionUID et vous devez l'examiner en profondeur.
Fondamentalement, si vous ne mettez pas à jour la version correctement lorsque vous mettez à jour une classe que vous devez écrire / lire, vous obtiendrez une erreur lorsque vous essayez de lire les anciennes données.
la source