Warum wird die serialVersionUID
nicht automatisch generiert? Ich stieß auf ein Problem auf einem Anwendungsserver, bei dem anscheinend eine alte Klasse zwischengespeichert wurde.Warum wird die serialVersionUID nicht automatisch generiert?
Antwort
serialVersionUID wird nicht automatisch generiert, weil es gefährlich ist. Wenn serialversionuid gesetzt ist, bedeutet dies, dass zwei Versionen einer Klasse in Bezug auf die Serialisierung kompatibel sind.
Stellen Sie sich vor Sie haben eine Klasse namens Foo, und es hat keine serialversionuid (der Standard), und Sie serialisieren eine Instanz von Foo in eine Datei. Später fügst du einige neue Mitglieder zur Foo-Klasse hinzu. Wenn Sie versuchen, das Foo-Objekt aus der Datei zu deserialisieren, erhalten Sie einen Serialisierungsfehler, der besagt, dass die Objekte nicht kompatibel sind. Sie sind inkompatibel, das ist was Sie wollen und ist die Standardeinstellung. Sie sind nicht kompatibel, da neue Member in der Foo-Klasse nicht von der alten serialisierten Instanz von Foo initialisiert werden können.
Jetzt könnten Sie sagen, "Es ist mir egal, in meiner Anwendung ist es akzeptabel für diese Felder nicht initialisiert werden". Wenn das wirklich der Fall ist, können Sie die serialversionuid der neue Foo-Klasse auf die gleiche wie die alte Foo-Klasse. Dies teilt Java mit, dass die Objekte in Bezug auf Serialität kompatibel sind, und Java wird sich nicht beschweren, wenn Sie die alte Foo-Instanz in die neue Foo-Klasse deserialisieren (die neuen Felder sind jedoch weiterhin nicht initialisiert).
Wenn Sie eine neue Klasse zum ersten Mal erstellen, und Sie die serialVersionUID gesetzt, Sie einen Vertrag eintreten. Dieser Vertrag ist, "Für alle zukünftigen Versionen dieser Klasse mit der gleichen serialversionuid, werde ich garantieren, dass sie in Bezug auf Zustand und Serialisierung kompatibel sind".
Wenn Sie eine Klasse zu ändern, und Sie explizit wollen Deserialisierung von alten Versionen nicht zulassen, können Sie die serialVersionUID auf einen neuen Wert ändern. Dies führt dazu, dass eine Ausnahme ausgelöst wird, wenn versucht wird, ein altes Objekt in eine neue Klasseninstanz zu deserialisieren.
Es wird automatisch generiert, basierend auf der Struktur der Klasse. Ändert sich die Struktur, wird die ID regeneriert (nach der serialization specification ist es ein hashof der Klasse).
Sie sollten also eine explizite serialVersionUID
definieren.
_So sollten Sie besser eine explizite serialVersionUID definieren._ Sie haben recht, aber sie sollten besser wissen, was zu tun ist, um diese Variable in Bezug auf die serialisierte Form der Klasse zu verwalten, oder es ist eine Übung in Vergeblichkeit. – McDowell
Guter Punkt, eine Menge Dokumentation darüber (die ich durchlesen muss). –
Wenn Sie Eclipse als IDE verwenden, können Sie mit der rechten Maustaste auf die Warnung über die fehlende serialVersionUID und Sie werden zwei Optionen erhalten:
1) Definieren Sie den Eclipse-Standard, der den Wert 1L hat ; oder
2) Definieren Sie einen zufällig generierten langen Wert
Wenn Sie sich für die Versionsverwaltung von serialisierten Objekten interessieren, müssen Sie bei jeder Änderung der Klasse einen neuen Wert manuell neu generieren. Die Javadoc für den Serializable Schnittstelle hat dies zu sagen, was passiert, wenn man überhaupt keine serialVersionUID erklären:
Wenn eine serializable Klasse nicht explizit eine serialVersionUID erklären, dann wird die Serialisierung Laufzeit eine Standard serialVersionUID berechnen Wert für diese Klasse basierend auf verschiedenen Aspekten der Klasse, wie in der Java (TM) Object Serialization Specification beschrieben. Es wird jedoch dringend empfohlen, dass alle serialisierbaren Klassen serialVersionUID-Werte explizit deklarieren, da die standardmäßige serialVersionUID-Berechnung äußerst empfindlich auf Klassendetails reagiert, die je nach Compilerimplementierungen variieren und daher bei der Deserialisierung zu unerwarteten InvalidClassExceptions führen können. Um einen konsistenten serialVersionUID-Wert in verschiedenen Java-Compiler-Implementierungen zu gewährleisten, muss daher eine serialisierbare Klasse einen expliziten serialVersionUID-Wert deklarieren.
In der Praxis habe ich auch gefunden, wenn Sie mit identischen Quellcode auf zwei oder mehr Maschinen (ausgecheckt von Subversion, zum Beispiel) beginnen, wo serialVersionUID in einer Klasse nicht definiert wurde, der Compiler generierten Wert in Die Klasse unterscheidet sich auf jeder Maschine, wenn der Code kompiliert wird. Dies kann zu verwirrenden Fehlern während der Entwicklung führen.
Wenn Sie sicher sind, dass Sie nie eine Situation haben werden, in der veraltete serialisierte Objekte nicht mehr synchron mit einer neueren Version der Klasse sind (oder zwei JVMs, die serialisierte Objekte ohne Synchronisation senden) andere, vielleicht über eine Netzwerk-oder Socket-Verbindung) dann einfach einen Wert von 1L für serialVersionUID und lassen Sie es so für immer.
http://download-llnw.oracle.com/javase/6/docs/api/java/io/Serializable.html
"Zufällig" ist nicht dasselbe wie "erzeugt". Für die gleiche (oder ähnlich genug) Quelldatei bin ich mir ziemlich sicher, dass das Tool Ihnen garantiert die gleiche UUID geben wird. –
"Sie müssen bei jeder Änderung der Klasse einen neuen Wert manuell neu generieren". Definitiv nicht. Dies ist genau das Gegenteil von dem, was Sie tun sollten. – EJP
Und der Standardwert ist nicht 1L. – EJP
Das macht Sinn. Das ist etwas anderes, worüber ich nachdenken sollte. –
Nicht sicher, warum dies als richtige Antwort markiert ist, da serialVersionUID * automatisch generiert wird. Darüber hinaus kann es in Abhängigkeit von der Situation einen Wert in automatisch erzeugten IDs geben, da sie eine neue Nummer sicherstellen, wenn die Klasse modifiziert wird, anstatt dass jemand den Code ändert und dann vergisst. Aber offensichtlich nicht für alle Fälle, wie dieser Beitrag richtig zeigt. – nilskp
Das ist so einfach, und dennoch verstehen so wenige Leute es (oder können es gestört werden, es zu verstehen?). Ich rate von der Menge an Caps Lock, die Sie verwenden, dass Sie auch dadurch frustriert sind. –