Wenn die Klasse Serializable in Eclipse implementiert, habe ich zwei Optionen: Standard serialVersionUID(1L)
hinzufügen oder serialVersionUID(3567653491060394677L)
generieren. Ich denke, dass der erste ist cooler, aber oft sah ich Leute mit der zweiten Option. Gibt es einen Grund, long serialVersionUID
zu generieren?Warum lange serialVersionUID anstelle eines einfachen 1L generieren?
Antwort
Soweit ich das beurteilen kann, wäre dies nur für die Kompatibilität mit früheren Versionen. Dies wäre nur nützlich, wenn Sie davor versäumt hätten, eine serialVersionUID zu verwenden, und dann eine Änderung vorgenommen hätten, von der Sie wissen, dass sie compatible sein sollte, die aber die Serialisierung unterbricht.
Siehe die Java Serialization Spec für weitere Details.
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, die dann geändert wird, wenn der Klasse neue Details hinzugefügt werden, z. B. ein neues Feld, das sich auf die Struktur der Serialisierung auswirken würde Objekt.
Immer mit der gleichen ID, wie 1L
bedeutet, dass in Zukunft, wenn die Klassendefinition geändert wird, die Änderungen an der Struktur des serialisierten Objekts verursacht, wird es eine gute Chance, Probleme beim Deserialisieren eines Objekts .
Wenn die ID weggelassen wird, berechnet Java die ID tatsächlich anhand der Felder des Objekts, aber ich glaube, dass es ein teurer Prozess ist. Wenn Sie einen manuell bereitstellen, wird die Leistung verbessert.
Hier sind ein paar Links zu Artikeln, die Serialisierung und Versionierung von Klassen diskutieren:
- JDC Tech Tips: February 29, 2000(Link gebrochen ab Februar 2013)
- Discover the secrets of the Java Serialization API
Die Idee hinter der Verwendung von 1L ist, dass Sie es jedes Mal erhöhen, wenn Sie die Klasseneigenschaften oder Methoden ändern. – Powerlord
Vielen Dank für die Informationen :) – coobird
Es gibt keine Auswirkungen auf die Laufzeitleistung, da die serialversionUID automatisch generiert werden kann - sie wird bei der Kompilierung von javac generiert ... Wenn Sie den Bytecode der Klasse dekompilieren, sehen Sie die Variable tatsächlich statisch der Bytecode. – Jared
der Hauptgrund, Für den generierten wäre es kompatibel mit einer vorhandenen Version der Klasse, die bereits persistente Kopien hat.
OK übernommen, aber das gleiche wird sein, wenn ich immer 1L habe. Alles wird kompatibel sein, auch wenn ich etwas ändern werde. – grep
@grep versuchen, ein Feld umzubenennen und dann sehen, was passiert. – Trejkaz
@grep der Punkt ist, dass, wenn Sie eine Klasse haben, die die serialVersionUID zuvor weggelassen, es automatisch generiert bekommen hätte. Jetzt möchten Sie es also explizit einstellen. Wenn Sie es auf 1L setzen, wäre es mit der vorhandenen Klasse inkompatibel, während die Verwendung des generierten Werts es kompatibel hält. – marc82ch
Wenn Sie keine serialVersionUID angeben, wird diese von Java im laufenden Betrieb erstellt. Die generierte serialVersionUID ist diese Nummer. Wenn Sie etwas in Ihrer Klasse ändern, das Ihre Klasse nicht wirklich inkompatibel mit früheren serialisierten Verisons macht, sondern den Hash ändert, dann müssen Sie die generierte sehr große Zahl serialVersionUID (oder die "erwartete" Zahl aus der Fehlermeldung) verwenden . Ansonsten, wenn Sie selbst alles im Auge behalten, ist 0, 1, 2 ... besser.
Sie meinten ==> 1. Wenn Sie möchten, dass verschiedene Klassenänderungen kompatibel sind, verwenden Sie die generierte. 2. Wenn Sie möchten, dass verschiedene Versionen von Klassen inkompatibel sind, verwenden Sie die Standardeinstellung 1, und achten Sie darauf, dass die Klassen inkrementiert werden.Habe ich es richtig verstanden? – JavaDeveloper
Der "lange" Standardwert von serialVersionUID
ist der Standardwert, wie in Java Serialization Specification definiert, berechnet aus dem Standardserialisierungsverhalten.
Wenn Sie also die Standardversionsnummer hinzufügen, wird Ihre Klasse schneller (serialisiert), solange sich nichts strukturell verändert hat, aber Sie müssen darauf achten, dass Sie die Klasse ändern (Felder hinzufügen/entfernen) Sie aktualisieren auch die Seriennummer.
Wenn Sie nicht mit vorhandenen Bitströmen kompatibel sein müssen, können Sie einfach 1L
dorthin setzen und die Version bei Bedarf nach Bedarf inkrementieren. Das heißt, wenn die standardmäßige Serialisierungsversion der geänderten Klasse sich von der Standardversion der alten Klasse unterscheidet.
Sie sollten unbedingt jedes Mal eine serialVersionUID erstellen, wenn Sie eine Klasse definieren, die java.io.Serializable
implementiert. Wenn Sie dies nicht tun, wird automatisch für Sie erstellt, aber das ist schlecht. Die automatisch generierte serialVersionUID basiert auf den Methodensignaturen Ihrer Klasse, also Wenn Sie Ihre Klasse in der Zukunft ändern, um eine Methode hinzuzufügen ( ), wird die Deserialisierung der "alten" Versionen der Klasse fehlschlagen. Hier ist, was passieren kann:
- Erstellen Sie die erste Version der Klasse, ohne zu definieren, die serialVersionUID.
- Serialisieren Sie eine Instanz Ihrer Klasse in einen persistenten Speicher. Eine serialVersionUID wird automatisch für Sie generiert.
- Ändern Sie Ihre Klasse, um eine neue Methode hinzuzufügen, und implementieren Sie Ihre Anwendung erneut.
- Versuch, die Instanz zu deserialisieren, die in Schritt 2 serialisiert wurde, aber jetzt fehlschlägt (wenn es erfolgreich sein sollte), da es eine andere automatisch generierte serialVersionUID hat.
@Downvoters Kannst du den Grund für Downvotes angeben? –
In der Tat sollte die Deserialisierung alter Versionen der Klasse in der Tat fehlschlagen, weil sie nicht mehr die gleichen sind. Sie schlagen vor, serialVersionUID selbst zu generieren, um Serialisierungsfehler zu verhindern, wenn sich die Klassensignatur ändert. Obwohl Ihr Vorschlag angemessen ist, ist Ihre Erklärung des Zwecks einfach falsch und irreführend. Es wäre klug, deine Antwort zu modifizieren. – mostruash
@mostruash go ahed ... schön, dein Update zu sehen ... –
Da in vielen Fällen Standard-ID nicht eindeutig ist. So erstellen wir ID für ein einzigartiges Konzept.
Können Sie Ihre Antwort bearbeiten, um es mehr auszufüllen? Das scheint hier ein Kommentar zu sein. Vielen Dank. – Gray
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 serialVersionUID-Wert 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 sie automatisch mit einem Wert hinzu, der basierend auf den in der Klasse deklarierten Feldern generiert wird.
Wenn Sie serialVersionUID (1L) anstelle von serialVersionUID (3567653491060394677L) verwenden, sagen Sie etwas.
Sie sagen, dass Sie zu 100% sicher sind, dass kein System, das jemals diese Klasse berühren wird, die eine inkompatible serialisierte Version dieser Klasse mit einer Versionsnummer von 1.
hat Wenn Sie irgendeine Entschuldigung denken kann Es ist eine serialisierte Versionshistorie, die unbekannt ist, was schwer zu sagen ist. Zu Lebzeiten wird eine erfolgreiche Klasse von vielen Menschen gepflegt, in vielen Projekten gelebt und in vielen Systemen residiert.
Sie können sich darüber quälen. Oder Sie können im Lotto spielen und hoffen, dass Sie verlieren. Wenn Sie die Version generieren, haben Sie eine winzige Chance, dass etwas schief läuft. Wenn Sie annehmen "Hey, ich wette, niemand hat noch 1 benutzt" sind Ihre Chancen größer als winzig. Gerade weil wir alle denken, 0 und 1 sind cool, haben Sie höhere Chancen, sie zu treffen.
-
Wenn Sie erzeugen serialVersionUID (3567653491060394677L) statt verwenden serialVersionUID (1 l) Sie etwas sagen.
Sie sagen, dass Leute möglicherweise andere Versionsnummern über der Geschichte dieser Klasse entweder manuell erstellt oder erzeugt haben, und Sie interessieren sich nicht, weil Longs große Zahlen verdrecken.
In jedem Fall, wenn Sie die Versionsnummern, die beim Serialisieren der Klasse im gesamten Universum, wo es existiert oder jemals existieren wird, perfekt kennen, werden Sie eine Chance nutzen.Wenn Sie die Zeit haben, 100% sicher zu machen, dass 1 AOK ist, gehen Sie dafür. Wenn das zu viel Arbeit ist, mach weiter und erzeuge blind die Nummer. Sie werden eher im Lotto gewinnen, als dass das schief geht. Wenn ja, lass es mich wissen und ich kaufe dir ein Bier.
Mit all dem Gerede über das Lottospielen habe ich Ihnen vielleicht den Eindruck vermittelt, dass serialVersionUID zufällig generiert wird. In der Tat, solange der Bereich der Zahlen gleichmäßig über jeden möglichen Wert eines Long verteilt ist, wäre das in Ordnung. Allerdings ist es tatsächlich so gemacht:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
Der einzige Unterschied, den Sie mit, dass zu bekommen ist, dass Sie keine Quelle von Zufalls benötigen. Sie verwenden die Änderungen in der Klasse selbst, um das Ergebnis zu ändern. Aber nach dem Schubladprinzip besteht immer noch die Möglichkeit, dass es schief gehen könnte und eine Kollision hätte. Es ist unglaublich unwahrscheinlich. Also viel Glück, ein Bier aus mir zu holen.
Aber selbst wenn die Klasse nur in einem System und einer Codebasis lebt, denken Sie, dass das Erhöhen der Zahl von Hand keine Kollision bedeutet, bedeutet nur, dass Sie Menschen nicht verstehen. :)
Wenn ein "System" die Klasse berührt, d. H. Die Klasse so ändert, dass die Serialisierung inkompatibel wird, stellt sich die Frage, ob dieses System auch die serialVersionUID ändert. Ich denke nicht, dass die Chancen geringer sind, dass es daran erinnert wird, es zu ändern, wenn es lang ist. Ich denke eher das Gegenteil ist wahr, wenn die Zahl leichter zu merken ist, sind die Änderungen höher, dass ich bemerke, dass ich es aus Versehen nicht geändert habe. –
Das ist falsch! Wenn Sie serialVersionUID generieren und diesen Wert in Ihrem Quellcode deklarieren, anstatt 1L oder nichts, sagen Sie tatsächlich: Ich möchte eine möglicherweise unbemerkte Kollision in der Zukunft mit undefinierten Effekten, und ich möchte nicht, dass Java oder irgendwelche Menschen dies verhindern . Java ist paranoid, aber gehorsam. Menschen machen normalerweise keine großen Zahlen. Auf diese Weise kann Java, wenn sich die Klasse ändert, alte inkompatible Versionen deserialisieren. MwoaHaHa ...;) – Superole
Wie ist das genaue Duplikat? Ich frage nicht, warum es überhaupt generiert, aber warum lange serialVersionUID generieren. – IAdapter
Wenn Jon Skeet serialVersionUID verwendet, verwendet er 0L: http://stackoverflow.com/questions/605828/does-it-matter-what-ichoose-for-serialversionuid-when-extending-serializable-cla/605832#605832 ;) –
@HannoFietz: Der genaue Satz lautet: "Der Einfachheit halber würde ich vorschlagen ** mit ** beginnen und mit ** bei jedem Mal um 1 erhöhen **." Es hört sich so an, als würde er '0L' nur anfänglich verwenden. –