Wenn die Klasse Serializable in Eclipse implementiert, habe ich zwei Optionen: Standard hinzufügen serialVersionUID(1L)
oder generiert serialVersionUID(3567653491060394677L)
. Ich denke, dass der erste cooler ist, aber oft habe ich Leute gesehen, die die zweite Option benutzt haben. Gibt es einen Grund zu generieren long serialVersionUID
?
210
0L
nur anfänglich verwenden.Antworten:
Soweit ich das beurteilen kann, wäre dies nur aus Gründen der Kompatibilität mit früheren Versionen möglich. Dies ist nur dann nützlich, wenn Sie zuvor die Verwendung einer serialVersionUID versäumt haben und dann eine Änderung vorgenommen haben, von der Sie wissen, dass sie kompatibel sein sollte, die jedoch dazu führt, dass die Serialisierung unterbrochen wird .
Weitere Informationen finden Sie in der Java-Serialisierungsspezifikation .
quelle
Der Zweck der UID der Serialisierungsversion besteht darin, verschiedene Versionen einer Klasse zu verfolgen, um eine gültige Serialisierung von Objekten durchzuführen.
Die Idee ist, eine ID zu generieren, die für eine bestimmte Version einer Klasse eindeutig ist. Diese wird dann geändert, wenn der Klasse neue Details hinzugefügt werden, z. B. ein neues Feld, das sich auf die Struktur des serialisierten Objekts auswirkt.
1L
Wenn Sie immer dieselbe ID verwenden, z. B. wenn in Zukunft die Klassendefinition geändert wird, was zu Änderungen an der Struktur des serialisierten Objekts führt, besteht eine gute Wahrscheinlichkeit, dass beim Versuch, ein Objekt zu deserialisieren, Probleme auftreten.Wenn die ID weggelassen wird, berechnet Java die ID für Sie basierend auf den Feldern des Objekts. Ich glaube jedoch, dass dies ein teurer Prozess ist. Wenn Sie also eine ID manuell bereitstellen, wird die Leistung verbessert.
Hier sind einige Links zu Artikeln, die die Serialisierung und Versionierung von Klassen behandeln:
quelle
Note - It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.
Der obige Kommentar stammt aus der Java Object Serialization Specification Version 6.0Der Hauptgrund für die generierte Version besteht darin, sie mit einer vorhandenen Version der Klasse kompatibel zu machen, die bereits Kopien beibehalten hat.
quelle
Der "lange" Standardwert von
serialVersionUID
ist der Standardwert, der in der Java-Serialisierungsspezifikation definiert ist und aus dem Standard-Serialisierungsverhalten berechnet wird.Wenn Sie also die Standardversionsnummer hinzufügen, wird Ihre Klasse schneller (de-) serialisiert, solange sich nichts strukturell geändert hat. Sie müssen jedoch darauf achten, dass Sie beim Ändern der Klasse (Hinzufügen / Entfernen von Feldern) auch die aktualisieren Ordnungsnummer.
Wenn Sie nicht mit vorhandenen Bitströmen kompatibel sein müssen, können Sie sie einfach
1L
dort ablegen und die Version nach Bedarf erhöhen, wenn sich etwas ändert. Das heißt, wenn sich die Standardversion der Serialisierung der geänderten Klasse von der Standardversion der alten Klasse unterscheidet.quelle
Sie sollten unbedingt jedes Mal eine serialVersionUID erstellen, wenn Sie eine Klasse definieren, die implementiert wird
java.io.Serializable
. Wenn Sie dies nicht tun, wird automatisch eine für Sie erstellt, aber das ist schlecht. Die automatisch generierte serialVersionUID basiert auf den Methodensignaturen Ihrer Klasse. Wenn Sie also Ihre Klasse in Zukunft ändern, um beispielsweise eine Methode hinzuzufügen, schlägt die Deserialisierung der "alten" Versionen der Klasse fehl. Folgendes kann passieren:quelle
Wenn Sie keine serialVersionUID angeben, erstellt Java eine im laufenden Betrieb. Die generierte serialVersionUID ist diese Nummer. Wenn Sie etwas in Ihrer Klasse ändern, das Ihre Klasse nicht wirklich mit früheren serialisierten Versionen inkompatibel macht, sondern den Hash ändert, müssen Sie die generierte serialVersionUID mit sehr großer Nummer (oder die "erwartete" Nummer aus der Fehlermeldung) verwenden. . Andernfalls ist 0, 1, 2 ... besser, wenn Sie alles selbst im Auge behalten.
quelle
Wenn Sie serialVersionUID (1L) verwenden, anstatt serialVersionUID (3567653491060394677L) zu generieren, sagen Sie etwas.
Sie sagen, dass Sie zu 100% sicher sind, dass kein System, das diese Klasse jemals berühren wird, eine inkompatible serialisierte Version dieser Klasse mit der Versionsnummer 1 hat.
Wenn Sie sich eine Entschuldigung dafür vorstellen können, dass der Verlauf der serialisierten Version unbekannt ist, ist dies möglicherweise schwer mit Sicherheit zu sagen. Zu Lebzeiten wird eine erfolgreiche Klasse von vielen Menschen gepflegt, in vielen Projekten gelebt und in vielen Systemen untergebracht.
Darüber können Sie sich quälen. Oder Sie können im Lotto spielen und hoffen zu verlieren. Wenn Sie die Version generieren, besteht eine geringe Wahrscheinlichkeit, dass etwas schief geht. Wenn Sie davon ausgehen, dass "Hey, ich wette, noch hat niemand 1 verwendet", sind Ihre Chancen größer als winzig. Gerade weil wir alle 0 und 1 für cool halten, haben Sie höhere Chancen, sie zu treffen.
- -
Wenn Sie serialVersionUID (3567653491060394677L) generieren, anstatt serialVersionUID (1L) zu verwenden, sagen Sie etwas.
Sie sagen, dass die Leute im Laufe der Geschichte dieser Klasse möglicherweise andere Versionsnummern manuell erstellt oder generiert haben, und es ist Ihnen egal, weil Longs große Zahlen ausflippen.
In beiden Fällen gehen Sie ein Risiko ein, es sei denn, Sie kennen den Verlauf der Versionsnummern, die bei der Serialisierung der Klasse im gesamten Universum, in dem sie existiert oder jemals existieren wird, verwendet werden, genau. Wenn Sie die Zeit haben, 100% sicher zu stellen, dass 1 AOK ist, machen Sie es. Wenn das zu viel Arbeit ist, generieren Sie die Nummer blind. Es ist wahrscheinlicher, dass Sie im Lotto gewinnen, als dass dies schief geht. Wenn ja, lass es mich wissen und ich kaufe dir ein Bier.
Bei all dem Gerede über das Lotto spielen habe ich vielleicht den Eindruck erweckt, dass serialVersionUID zufällig generiert wird. In der Tat, solange der Zahlenbereich gleichmäßig über jeden möglichen Wert eines Long verteilt ist, wäre das in Ordnung. Es wird jedoch tatsächlich so gemacht:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
Der einzige Unterschied, den Sie dabei bekommen, ist, dass Sie keine Zufallsquelle benötigen. Sie verwenden die Änderungen in der Klasse selbst, um das Ergebnis zu ändern. Nach dem Pigeonhole-Prinzip besteht jedoch immer noch die Möglichkeit, dass ein Fehler auftritt und eine Kollision auftritt. Es ist einfach unglaublich unwahrscheinlich. Also viel Glück, ein Bier aus mir herauszuholen.
Selbst wenn die Klasse immer nur in einem System und einer Codebasis leben wird, bedeutet der Gedanke, dass das Erhöhen der Zahl von Hand keine Kollisionswahrscheinlichkeit bietet, nur, dass Sie Menschen nicht verstehen. :) :)
quelle
Nun, serialVersionUID ist eine Ausnahme von der Regel, dass "statische Felder nicht serialisiert werden". ObjectOutputStream schreibt jedes Mal den Wert von serialVersionUID in den Ausgabestream. ObjectInputStream liest es zurück und wenn der aus dem Stream gelesene Wert nicht mit dem Wert serialVersionUID in der aktuellen Version der Klasse übereinstimmt, wird die InvalidClassException ausgelöst. Wenn in der zu serialisierenden Klasse keine serialVersionUID offiziell deklariert ist, fügt der Compiler diese automatisch mit einem Wert hinzu, der basierend auf den in der Klasse deklarierten Feldern generiert wird.
quelle
Weil in vielen Fällen die Standard-ID nicht eindeutig ist. Deshalb erstellen wir eine ID, um ein einzigartiges Konzept zu erstellen.
quelle
Um die Antwort von @David Schmitts zu ergänzen, würde ich als Faustregel immer die Standard-1L außerhalb der Konvention verwenden. Ich musste nur ein paar Mal zurückgehen und einige davon ändern, aber ich wusste das, als ich die Änderung vornahm und die Standardnummer jedes Mal um eins aktualisierte.
In meiner aktuellen Firma benötigen sie die automatisch generierte Nummer, daher verwende ich diese für die Konvention, aber ich bevorzuge die Standardeinstellung. Wenn es sich nicht um eine Konvention handelt, bei der Sie arbeiten, verwenden Sie die Standardeinstellung, es sei denn, Sie glauben, dass Sie aus irgendeinem Grund die Struktur Ihrer serialisierten Klassen ständig ändern werden.
quelle
Der Zweck der UID der Serialisierungsversion besteht darin, verschiedene Versionen einer Klasse zu verfolgen, um eine gültige Serialisierung von Objekten durchzuführen.
Die Idee ist, eine ID zu generieren, die für eine bestimmte Version einer Klasse eindeutig ist. Diese wird dann geändert, wenn der Klasse neue Details hinzugefügt werden, z. B. ein neues Feld, das sich auf die Struktur des serialisierten Objekts auswirkt.
Eine einfache Erklärung:
Serialisieren Sie Daten?
Bei der Serialisierung werden im Grunde Klassendaten in eine Datei / einen Stream / etc. Geschrieben. Bei der De-Serialisierung werden diese Daten in eine Klasse zurückgelesen.
Beabsichtigen Sie, in Produktion zu gehen?
Wenn Sie nur etwas mit unwichtigen / gefälschten Daten testen, machen Sie sich darüber keine Sorgen (es sei denn, Sie testen die Serialisierung direkt).
Ist das die erste Version?
Wenn ja, setzen Sie serialVersionUID = 1L.
Ist dies die zweite, dritte usw. Produktversion?
Jetzt müssen Sie sich um serialVersionUID kümmern und sollten sich eingehend damit befassen.
Wenn Sie die Version beim Aktualisieren einer Klasse, die Sie schreiben / lesen müssen, nicht korrekt aktualisieren, wird im Grunde eine Fehlermeldung angezeigt, wenn Sie versuchen, alte Daten zu lesen.
quelle