La sérialisation Java - java.io.InvalidClassException classe locale incompatible
J'ai une classe publique, qui implémente Serializable, qui est prolongée par plusieurs autres classes. Seuls les sous-classes ont jamais été sérialisé avant - jamais de la super-classe.
La super-classe a défini un serialVersionUID.
Je ne sais pas si c'est important, mais il n'a pas été marqué comme privé, mais plutôt il a juste eu le défaut de protection, vous pourriez dire que c'était package protégé
static final long serialVersionUID = -7588980448693010399L;
La super-classe, ni aucune des sous-classes, toutefois mis en œuvre des méthodes readObject ou writeObject, et aucune des sous-classes avait expressément une serialVersionUID. J'ai pensé que celui défini dans la super-classe serait suffisant.
Malgré tout cela, les choses étaient bien dans la lecture précédemment objets sérialisés jusqu'à ce qu'une nouvelle variable d'instance, une Liste/liste de tableaux, avec une nouvelle formule a été ajouté à la super-classe, et certaines variables d'instance ont été ajoutés à l'un de ses sous-classes.
Maintenant lorsque j'essaie de lire auparavant les objets sérialisés, une exception est levée. L'un de semblable à ceci:
com.SomeCompany.SomeSubClass; local class incompatible: stream classdesc serialVersionUID = 1597316331807173261, local class serialVersionUID = -3344057582987646196
Je suppose que c'est dû au fait que la valeur par défaut serialVersionUID, qui a été utilisé parce que je n'ai pas de déclarer dans aucune des sous-classes, a maintenant changé en raison de changements dans la super-classe et une sous-classe.
Des Suggestions sur la façon de sortir de ce dilemme serait appréciée. Je suppose que j'ai besoin pour mettre en œuvre les méthodes readObject et writeObject, mais d'autres que de se prévaloir de defaultReadObject() et defaultWriteObject(), je ne suis pas exactement sûr de ce que je dois faire. Je ne sais si je dois ajouter serialVerisonUIDs à toutes les sous-classes ou si les méthodes readObject et writeObject doivent être mises en œuvre par chaque sous-classe, ou si je peux tout mettre en œuvre une fois, en supposant que je dois à tous, dans la superclasse.
Vous devez vous connecter pour publier un commentaire.
@DanielChapman donne une bonne explication de serialVersionUID, mais pas de solution. la solution est: d'exécuter le
serialver
programme sur tous vos vieux classes. mettre cesserialVersionUID
valeurs dans votre actuel versions des classes. aussi longtemps que la présente classes sont de série compatible avec les anciennes versions, vous devriez être bien. (note pour l'avenir de code: vous devriez toujours ont unserialVersionUID
sur tousSerializable
classes)si les nouvelles versions sont pas série compatible, alors vous avez besoin de faire un peu de magie avec une coutume
readObject
de mise en œuvre (vous n'aurez besoin que d'une coutumewriteObject
si vous étiez en train d'écrire nouveau de données de classe qui serait compatible avec l'ancien code). généralement parlant ajoutant ou en supprimant des champs de la classe de ne pas faire une classe de série incompatible. changer le type de champs existants, généralement.Bien sûr, même si la nouvelle classe est série compatible, vous pouvez toujours personnalisé
readObject
mise en œuvre. vous souhaitez peut-être cette si vous souhaitez remplir dans tous les nouveaux domaines qui sont manquantes à partir des données enregistrées à partir d'anciennes versions de la classe (par exemple, vous avez un nouveau champ de la Liste dont vous souhaitez initialiser une liste vide lors du chargement des anciens de la classe de données).La réponse courte est ici la série ID est calculée à partir d'un hash si vous ne spécifiez pas d'elle. (Les membres statiques ne sont pas héritées--ils sont statiques, il n'y a qu' (1) et il appartient à la classe).
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html
Si vous modifiez une classe ou de sa hiérarchie de votre hash sera différent. C'est une bonne chose. Vos objets sont différents maintenant qu'ils ont les différents membres. En tant que tel, si vous le lire à partir de sa forme sérialisée en fait, c'est un autre objet, donc l'exception.
La réponse longue est la sérialisation est extrêmement utile, mais ne devrait probablement pas être utilisé pour la persistance à moins qu'il n'y a pas d'autre moyen de le faire. Ses une voie dangereuse à cause de ce que vous êtes en train de vivre. Vous devriez envisager une base de données, XML, un format de fichier et probablement un APC ou d'autres de la persistance de la structure pour un pur projet Java.
Pour moi, j'ai oublié d'ajouter de la valeur par défaut de série id.
Cela a fonctionné pour moi:
Si vous avez écrit votre Sérialisé objet de classe dans un fichier, puis a apporté certaines modifications aux fichiers et compilé, et puis vous essayez de lire un objet, puis ce sera le cas.
Oui, écrire les objets nécessaires à déposer à nouveau si une classe est modifiée et recompilée.
PS: Ce n'est PAS une solution; il était destiné à être une solution de contournement.