Warum lange serialVersionUID anstelle eines einfachen 1L generieren?

Wenn die class Serializable in Eclipse implementiert, habe ich zwei Optionen: füge standard serialVersionUID(1L) oder generiere serialVersionUID(3567653491060394677L) . Ich denke, dass der erste ist cooler, aber oft sah ich Leute mit der zweiten Option. Gibt es einen Grund, long serialVersionUID zu generieren?

   

    Soweit ich das beurteilen kann, wäre dies nur für die Kompatibilität mit früheren Releases. Dies wäre nur 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 die Serialisierung unterbricht.

    Weitere Informationen finden Sie in der Java-Serialisierungsspezifikation .

    Der Zweck der UID der Serialisierungsversion besteht darin, verschiedene Versionen einer class zu verfolgen, um eine gültige Serialisierung von Objekten durchzuführen.

    Die Idee besteht darin, eine ID zu generieren, die für eine bestimmte Version einer class eindeutig ist, die dann geändert wird, wenn der class neue Details hinzugefügt werden, beispielsweise ein neues Feld, das sich auf die Struktur des serialisierten Objekts auswirkt.

    Wenn Sie immer die gleiche ID verwenden, z. B. 1L bedeutet dies, dass bei einer Änderung der classndefinition, die Änderungen an der Struktur des serialisierten Objekts verursacht, in Zukunft Probleme beim Deserialisieren eines Objekts auftreten.

    Wenn die ID weggelassen wird, berechnet Java die ID für Sie basierend auf den Feldern des Objekts, aber ich glaube, dass es ein teurer process ist, so dass man manuell die Performance verbessern kann.

    Hier sind ein paar Links zu Artikeln, die die Serialisierung und Versionierung von classn behandeln:

    • JDC Tech Tips: 29. Februar 2000 (Link unterbrochen im Februar 2013)
    • Entdecken Sie die Geheimnisse der Java-Serialisierungs-API

    Der Hauptgrund für das Generierte wäre, es mit einer vorhandenen Version der class kompatibel zu machen, die bereits Kopien erhalten hat.

    Der “long” serialVersionUID der serialVersionUID ist der Standardwert, der durch die Java-Serialisierungsspezifikation definiert wird und aus dem Standardserialisierungsverhalten berechnet wird.

    Wenn Sie also die Standardversionsnummer hinzufügen, wird Ihre class schneller (serieller) serialisieren, solange sich nichts strukturell geändert hat, aber Sie müssen darauf achten, dass Sie die class auch aktualisieren, wenn Sie die class ändern (Felder hinzufügen / entfernen) Ordnungsnummer.

    Wenn Sie nicht mit bestehenden Bitstreams kompatibel sein müssen, können Sie einfach 1L dorthin setzen und die Version nach Bedarf inkrementieren, wenn sich etwas ändert. Das heißt, wenn die standardmäßige Serialisierungsversion der geänderten class sich von der Standardversion der alten class unterscheidet.

    Sie sollten unbedingt jedes Mal eine serialVersionUID erstellen, wenn Sie eine class definieren, die java.io.Serializable implementiert. 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 class. Wenn Sie also in Zukunft Ihre class ändern, um eine Methode hinzuzufügen (z. B.), schlägt die Deserialisierung der “alten” Versionen der class fehl. Folgendes kann passieren:

    1. Erstellen Sie die erste Version Ihrer class, ohne die serialVersionUID zu definieren.
    2. Serialisieren Sie eine Instanz Ihrer class in einen persistenten Speicher. Eine serialVersionUID wird automatisch für Sie generiert.
    3. Ändern Sie Ihre class, um eine neue Methode hinzuzufügen, und implementieren Sie Ihre Anwendung erneut.
    4. Es wurde versucht, die Instanz zu deserialisieren, die in Schritt 2 serialisiert wurde, aber jetzt schlägt sie fehl (wenn es erfolgreich sein sollte), da sie eine andere automatisch generierte serialVersionUID aufweist.

    Wenn Sie keine serialVersionUID angeben, wird sie von Java im laufenden Betrieb erstellt. Die generierte serialVersionUID ist diese Nummer. Wenn Sie etwas in Ihrer class ändern, das Ihre class 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.

    Wenn Sie serialVersionUID (1L) anstelle von serialVersionUID (3567653491060394677L) verwenden, sagen Sie etwas.

    Sie sagen, dass Sie 100% sicher sind, dass kein System jemals diese class mit einer inkompatiblen serialisierten Version dieser class mit einer Versionsnummer von 1 berühren wird.

    Wenn Sie sich eine Entschuldigung dafür vorstellen können, dass die Geschichte der serialisierten Version unbekannt ist, ist das schwer zu sagen. Zu Lebzeiten wird eine erfolgreiche class 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 serialVersionUID (3567653491060394677L) statt serialVersionUID (1L) generieren, sagen Sie etwas.

    Du sagst, dass Leute vielleicht andere Versionsnummern über die Geschichte dieser class manuell erstellt oder generiert haben, und es ist dir egal, weil Longs große Zahlen ausflippen.

    Wie auch immer, es sei denn, Sie kennen die Versionsnummer, die beim Serialisieren der class im gesamten Universum, wo sie existiert oder jemals existieren wird, perfekt kennen, nehmen Sie eine Chance. 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.

    Bei all dem Gerede vom Lottospielen habe ich Ihnen 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. Es ist jedoch tatsächlich so gemacht:

    http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100

    Der einzige Unterschied, den Sie damit bekommen, ist, dass Sie keine Zufallsquelle benötigen. Sie verwenden die Änderungen in der class 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 class nur in einem System und einer Codebasis leben wird, bedeutet die Annahme, dass die Erhöhung der Zahl von Hand die Wahrscheinlichkeit einer Kollision nicht erhöht, nur, dass Sie die Menschen nicht verstehen. 🙂

    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 class übereinstimmt, wird die InvalidClassException ausgetriggers. Wenn in der zu serialisierenden class keine serialVersionUID offiziell deklariert ist, fügt der Compiler sie automatisch mit einem Wert hinzu, der basierend auf den in der class deklarierten Feldern generiert wird.

    Weil die Standard-ID in vielen Fällen nicht eindeutig ist. So erstellen wir ID für ein einzigartiges Konzept.

    Um @David Schmitts Antwort zu addieren, würde ich als Faustregel immer die 1L-Standardkonvention verwenden. Ich musste nur ein paar Mal zurückgehen und einige von ihnen ändern, aber das wusste ich, als ich die Änderung vornahm und die Standardnummer jedes Mal um eins erhöhte.

    Bei meiner derzeitigen Firma benötigen sie die automatisch generierte Nummer, also verwende ich das für die Konvention, aber ich bevorzuge die Standardeinstellung. Mein Beispiel ist, wenn es sich nicht um eine Konvention handelt, bei der Sie arbeiten, verwenden Sie die Standardeinstellung, es sei denn, Sie denken, dass Sie die Struktur Ihrer serialisierten classn aus irgendeinem Grund ständig ändern werden.