serialVersionUID
Erleichtert die Versionierung serialisierter Daten. Sein Wert wird bei der Serialisierung mit den Daten gespeichert. Bei der De-Serialisierung wird dieselbe Version überprüft, um festzustellen, wie die serialisierten Daten mit dem aktuellen Code übereinstimmen.
Wenn Sie Ihre Daten versionieren möchten, beginnen Sie normalerweise mit einer serialVersionUID
0 und stoßen sie bei jeder strukturellen Änderung Ihrer Klasse an, die die serialisierten Daten ändert (Hinzufügen oder Entfernen nicht vorübergehender Felder).
Der integrierte De-Serialisierungsmechanismus ( in.defaultReadObject()
) verweigert die De-Serialisierung von alten Versionen der Daten. Wenn Sie möchten, können Sie Ihre eigene readObject () -Funktion definieren, mit der alte Daten zurückgelesen werden können. Dieser benutzerdefinierte Code kann dann überprüfen, serialVersionUID
in welcher Version sich die Daten befinden, und entscheiden, wie sie de-serialisiert werden sollen. Diese Versionierungstechnik ist nützlich, wenn Sie serialisierte Daten speichern, die mehrere Versionen Ihres Codes überleben.
Das Speichern von serialisierten Daten über einen so langen Zeitraum ist jedoch nicht sehr verbreitet. Es ist weitaus üblicher, den Serialisierungsmechanismus zu verwenden, um Daten vorübergehend in beispielsweise einen Cache zu schreiben oder über das Netzwerk an ein anderes Programm mit derselben Version der relevanten Teile der Codebasis zu senden.
In diesem Fall sind Sie nicht daran interessiert, die Abwärtskompatibilität aufrechtzuerhalten. Sie müssen nur sicherstellen, dass die kommunizierenden Codebasen tatsächlich dieselben Versionen der relevanten Klassen haben. Um eine solche Überprüfung zu vereinfachen, müssen Sie das serialVersionUID
Gleiche wie zuvor beibehalten und nicht vergessen, es zu aktualisieren, wenn Sie Änderungen an Ihren Klassen vornehmen.
Wenn Sie vergessen, das Feld zu aktualisieren, erhalten Sie möglicherweise zwei verschiedene Versionen einer Klasse mit unterschiedlicher Struktur, aber derselben serialVersionUID
. In diesem Fall erkennt der Standardmechanismus ( in.defaultReadObject()
) keinen Unterschied und versucht, inkompatible Daten zu de-serialisieren. Jetzt kann es zu einem kryptischen Laufzeitfehler oder einem stillen Fehler (Nullfelder) kommen. Diese Arten von Fehlern sind möglicherweise schwer zu finden.
Um diesen Anwendungsfall zu erleichtern, bietet Ihnen die Java-Plattform die Möglichkeit, die Einstellung nicht serialVersionUID
manuell vorzunehmen . Stattdessen wird zur Kompilierungszeit ein Hash der Klassenstruktur generiert und als ID verwendet. Dieser Mechanismus stellt sicher, dass Sie niemals unterschiedliche Klassenstrukturen mit derselben ID haben, sodass diese oben erwähnten schwer nachvollziehbaren Laufzeit-Serialisierungsfehler nicht auftreten.
Die automatisch generierte ID-Strategie hat jedoch einen Nachteil. Das heißt, dass sich die generierten IDs für dieselbe Klasse zwischen den Compilern unterscheiden können (wie oben von Jon Skeet erwähnt). Wenn Sie also serialisierte Daten zwischen Code kommunizieren, der mit verschiedenen Compilern kompiliert wurde, wird empfohlen, die IDs ohnehin manuell zu verwalten.
Und wenn Sie wie im ersten genannten Anwendungsfall abwärtskompatibel mit Ihren Daten sind, möchten Sie die ID wahrscheinlich auch selbst pflegen. Dies, um lesbare IDs zu erhalten und eine bessere Kontrolle darüber zu haben, wann und wie sie sich ändern.