serialVersionUID
erleichtert die Versionierung von serialisierten Daten. Sein Wert wird bei der Serialisierung zusammen mit den Daten gespeichert. Bei der De-Serialisierung wird dieselbe Version geprüft, um zu sehen, wie die serialisierten Daten mit dem aktuellen Code übereinstimmen.
Wenn Sie Ihre Daten versionieren wollen, beginnen Sie normalerweise mit einer serialVersionUID
von 0, und erhöhen Sie sie bei jeder strukturellen Änderung Ihrer Klasse, die die serialisierten Daten verändert (Hinzufügen oder Entfernen nicht transienter Felder).
Der eingebaute De-Serialisierungsmechanismus ( in.defaultReadObject()
) weigert sich, alte Versionen der Daten zu de-serialisieren. Aber wenn Sie wollen, können Sie Ihre eigene readObject() -Funktion, die alte Daten zurücklesen kann. Dieser benutzerdefinierte Code kann dann die serialVersionUID
um zu wissen, in welcher Version die Daten vorliegen, und um zu entscheiden, wie sie de-serialisiert werden sollen. Diese Versionierungstechnik ist nützlich, wenn Sie serialisierte Daten speichern, die mehrere Versionen Ihres Codes überdauern.
Die Speicherung von serialisierten Daten über einen so langen Zeitraum ist jedoch nicht sehr verbreitet. Viel häufiger wird der Serialisierungsmechanismus verwendet, um Daten vorübergehend z.B. in einen Zwischenspeicher zu schreiben oder sie über das Netz an ein anderes Programm mit derselben Version der relevanten Teile der Codebasis zu senden.
In diesem Fall sind Sie nicht an der Aufrechterhaltung der Abwärtskompatibilität interessiert. Es geht Ihnen nur darum, sicherzustellen, dass die Codebasen, die miteinander kommunizieren, tatsächlich die gleichen Versionen der relevanten Klassen haben. Um eine solche Prüfung zu ermöglichen, müssen Sie die serialVersionUID
wie bisher und vergessen Sie nicht, sie zu aktualisieren, wenn Sie Änderungen an Ihren Klassen vornehmen.
Wenn Sie vergessen, das Feld zu aktualisieren, haben Sie am Ende möglicherweise zwei verschiedene Versionen einer Klasse mit unterschiedlicher Struktur, aber mit der gleichen serialVersionUID
. Wenn dies geschieht, wird der Standardmechanismus ( in.defaultReadObject()
) wird keinen Unterschied feststellen und versuchen, inkompatible Daten zu de-serialisieren. Nun kann es zu einem kryptischen Laufzeitfehler oder einem stillen Fehler (Nullfelder) kommen. Diese Arten von Fehlern können schwer zu finden sein.
Um diesen Anwendungsfall zu unterstützen, bietet die Java-Plattform die Möglichkeit, die serialVersionUID
manuell. Stattdessen wird zur Kompilierzeit ein Hash der Klassenstruktur erzeugt und als id verwendet. Dieser Mechanismus stellt sicher, dass Sie niemals verschiedene Klassenstrukturen mit der gleichen ID haben, so dass die oben erwähnten, schwer zu verfolgenden Laufzeit-Serialisierungsfehler nicht auftreten.
Die Strategie der automatisch generierten IDs hat jedoch auch eine Kehrseite. Nämlich, dass die generierten IDs für dieselbe Klasse von Compiler zu Compiler unterschiedlich sein können (wie von Jon Skeet oben erwähnt). Wenn Sie also serialisierte Daten zwischen Code kommunizieren, der mit verschiedenen Compilern kompiliert wurde, sollten Sie die IDs auf jeden Fall manuell pflegen.
Und wenn Sie mit Ihren Daten rückwärtskompatibel sind, wie im ersten genannten Anwendungsfall, möchten Sie wahrscheinlich auch die ID selbst pflegen. Dies, um lesbare IDs zu erhalten und eine bessere Kontrolle darüber zu haben, wann und wie sie sich ändern.
7 Stimmen
Finden Sie eine gute Praxis über serialversionUID; dzone.com/articles/what-is-serialversionuid