Question

Je risque probablement quelques votes négatifs à ce sujet.

Il me semble que spécifier explicitement serialVersionUID pour les nouvelles classes est une mauvaise chose. Considérez les deux cas de non-modification lorsque la présentation a dû être modifiée et de modification lorsque cela n’aurait pas dû.

Ne pas changer quand cela aurait dû être changé ne se produit presque que quand il est explicite. Dans ce cas, il en résulte des bogues très subtils et difficiles à trouver. Surtout pendant le développement, quand la disposition des classes change souvent. Mais si cela n’a pas été explicitement spécifié, cela changera et la désérialisation se brisera fort, ce qui sera probablement résolu en purgeant le référentiel.

Le changer quand ne devrait pas se produire se produirait presque seulement quand il est implicite. C’est le cas rare où la disposition des classes a changé mais nous souhaitons toujours désérialiser les anciens blobs sérialisés. Cela sera probablement intercepté pendant le contrôle qualité ( Erreurs étranges après la mise à niveau de la version 5.2 à la version 5.2.1, voir la trace de pile ci-jointe ) et peut être corrigé de manière triviale en définissant une valeur explicite.

Commentaires?

Était-ce utile?

La solution

Changer le moment où cela ne devrait pas arriver peut arriver pour des raisons autres que les changements de disposition de classe - le problème est que cela dépend de la mise en œuvre du compilateur. Si vous déboguez avec Eclipse mais construisez des versions de production avec javac, vous pouvez vous retrouver avec deux ensembles de données incompatibles.

Autres conseils

Dans mon travail, nous interdisons explicitement de spécifier serialVersionUID, précisément à cause des problèmes que vous avez évoqués.

De plus, les classes que nous conservons ne sont utilisées que pour stocker des données sans aucune logique à l'intérieur. La seule façon de les modifier est donc due à la modification des membres des données.

pour insister davantage sur ce que dit John skeet et contredire le commentaire:

"Si vous n'en avez pas besoin (c'est-à-dire que vous sérialisez et désérialisez toujours avec la même version de classe), vous pouvez alors ignorer la déclaration explicite"

.

Même si vous ne sérialisez pas à long terme et utilisez la même version de classe, vous pouvez toujours rencontrer des problèmes . si vous écrivez du code client-serveur et que le code client peut fonctionner avec une version / implémentation jvm différente de celle du serveur, vous pouvez avoir les mêmes problèmes avec des serialversionuids incompatibles.

pour résumer, le seul moment où il est "sûr" Ne pas spécifier serialversionuids, c’est lorsque vous ne sérialisez pas à long terme et que vous êtes assuré que tous les consommateurs des données sérialisées utiliseront la même implémentation et la même version de JVM que le producteur original.

En bref, ne pas utiliser serialversionuid est généralement la situation la plus dommageable.

Lorsque vous devez prendre en charge la persistance à long terme via la sérialisation, vous devez presque toujours utiliser un code personnalisé pour la prendre en charge et définir explicitement le serialVersionUID . Sinon, l'ancienne version sérialisée ne sera pas utilisée. désérialisable par un code plus récent.

Ces scénarios requièrent déjà beaucoup de précautions pour résoudre correctement tous les cas, lorsque la classe change, de sorte que serialVersionUID est le moindre de vos problèmes.

Si vous n'en avez pas besoin (vous devez toujours sérialiser et désérialiser avec la même version de classe), vous pouvez alors ignorer la déclaration explicite, car la valeur calculée garantira que la version correcte est utilisée.

Que vous choisissiez serialVersionUID ou non (je vous suggère de le faire), vous devriez vraiment envisager de créer un ensemble complet de tests pour la compatibilité série.

Cela vaut également la peine de concevoir le format de série avec soin. C’est effectivement une API publique.

Si vous utilisez uniquement la sérialisation pour un appel de méthode à distance, par exemple. appeler un EJB, où les classes client et serveur et jvm sont identiques, ce que je soupçonne être de loin l'utilisation la plus courante, puis définir explicitement serialVersionUID (comme par exemple l'éclipse le suggère) risque de vous causer une douleur importante occasionnelle, Bogues inexplicables dans lesquels des instances de classe incompatibles sont traitées comme compatibles en raison de la série serialVersionUID fixée Les appels distants passeront inopinément pendant la sérialisation de bas niveau et le problème ne se posera que lorsque l'état de l'objet sera incohérent. Vous ne trouvez la source du problème que lorsque vous vous rendez compte que vos classes client et serveur sont quelque peu différentes (bien que serialVersionUID ne soit bien sûr pas le cas). Dans mon expérience, configurer serialVersionUID pour cette raison fait plus de mal que de bien.

Si, en revanche, vous définissez explicitement serialVersionUID pour lire les anciennes données, vous lisez par définition une version incompatible et vous risquez de vous retrouver avec un objet dans un état incohérent ou incomplet. Dans ce cas, paramétrer serialVersionUID est une solution de contournement pour un problème différent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top