serialVersionUID
facilite la version des données sérialisées. Sa valeur est stockée avec les données lors de la sérialisation. Lors de la désérialisation, la même version est vérifiée pour voir comment les données sérialisées correspondent au code actuel.
Si vous souhaitez mettre à jour vos données, vous commencez normalement par un serialVersionUID
de 0 et vous le remplacez à chaque modification structurelle de votre classe qui modifie les données sérialisées (ajout ou suppression de champs non transitoires).
Le mécanisme de désérialisation intégré ( in.defaultReadObject()
) refusera de désérialiser des anciennes versions des données. Mais si vous le souhaitez, vous pouvez définir votre propre fonction readObject () qui peut relire les anciennes données. Ce code personnalisé peut ensuite vérifier le serialVersionUID
afin de savoir dans quelle version les données se trouvent et décider comment les désérialiser. Cette technique de version est utile si vous stockez des données sérialisées qui survivent à plusieurs versions de votre code.
Mais le stockage de données sérialisées sur une période aussi longue n'est pas très courant. Il est beaucoup plus courant d'utiliser le mécanisme de sérialisation pour écrire temporairement des données dans un cache, par exemple, ou les envoyer sur le réseau à un autre programme avec la même version des parties pertinentes de la base de code.
Dans ce cas, vous ne souhaitez pas conserver la compatibilité descendante. Vous êtes uniquement soucieux de vous assurer que les bases de code qui communiquent ont bien les mêmes versions des classes pertinentes. Afin de faciliter une telle vérification, vous devez conserver le serialVersionUID
même que précédemment et ne pas oublier de le mettre à jour lorsque vous apportez des modifications à vos classes.
Si vous oubliez de mettre à jour le champ, vous pourriez vous retrouver avec deux versions différentes d'une classe avec une structure différente mais avec la même serialVersionUID
. Si cela se produit, le mécanisme par défaut ( in.defaultReadObject()
) ne détectera aucune différence et tentera de désérialiser les données incompatibles. Vous pouvez maintenant vous retrouver avec une erreur d'exécution cryptique ou une panne silencieuse (champs nuls). Ces types d'erreurs peuvent être difficiles à trouver.
Donc, pour aider à ce cas d'utilisation, la plate-forme Java vous offre le choix de ne pas définir serialVersionUID
manuellement. Au lieu de cela, un hachage de la structure de classe sera généré au moment de la compilation et utilisé comme id. Ce mécanisme s'assurera que vous n'avez jamais différentes structures de classe avec le même identifiant et vous n'obtiendrez donc pas les échecs de sérialisation d'exécution difficiles à retracer mentionnés ci-dessus.
Mais il y a un revers à la stratégie d'identification générée automatiquement. A savoir que les identifiants générés pour la même classe peuvent différer entre les compilateurs (comme mentionné par Jon Skeet ci-dessus). Donc, si vous communiquez des données sérialisées entre du code compilé avec différents compilateurs, il est recommandé de conserver les identifiants manuellement de toute façon.
Et si vous êtes rétrocompatible avec vos données comme dans le premier cas d'utilisation mentionné, vous souhaiterez probablement également conserver l'ID vous-même. Ceci afin d'obtenir des identifiants lisibles et d'avoir un meilleur contrôle sur quand et comment ils changent.