Frage

In Java werden statische und transiente Felder nicht serialisiert.Ich habe jedoch herausgefunden, dass die Initialisierung statischer Felder dazu führt, dass die generierte serialVersionUID geändert wird.Zum Beispiel, static int MYINT = 3; bewirkt, dass sich die serialVersionUID ändert.In diesem Beispiel ist dies sinnvoll, da verschiedene Versionen der Klasse unterschiedliche Anfangswerte erhalten würden.Warum ändert jede Initialisierung die serialVersionUID?Zum Beispiel, static String MYSTRING = System.getProperty("foo"); führt auch dazu, dass sich die serialVersionUID ändert.

Genauer gesagt ist meine Frage, warum die Initialisierung mit einer Methode dazu führt, dass sich die serialVersionUID ändert.Das Problem, auf das ich gestoßen bin, besteht darin, dass ich ein neues statisches Feld hinzugefügt habe, das mit einem Systemeigenschaftswert (getProperty) initialisiert wurde.Diese Änderung verursachte eine Serialisierungsausnahme bei einem Remoteaufruf.

War es hilfreich?

Lösung

Einige Informationen dazu finden Sie im Fehler 4365406 und in der Algorithmus zum Rechnen serialVersionUID.Grundsätzlich gilt, wenn Sie die Initialisierung Ihres ändern static Mitglied mit System.getProperty(), führt der Compiler ein neues ein static Eigenschaft in Ihrer Klasse, die auf die verweist System Klasse (ich gehe davon aus, dass die System (Klasse wurde zuvor in Ihrer Klasse nicht referenziert) und da diese vom Compiler eingeführte Eigenschaft nicht privat ist, nimmt sie an der teil serialVersionUID Berechnung.

Moral:Verwenden Sie immer explizit serialVersionUID, Sie sparen einige CPU-Zyklen und einige Kopfschmerzen :)

Andere Tipps

Die automatische serialVersionUID wird basierend auf Mitgliedern einer Klasse berechnet.Diese können für eine Klassendatei mit dem Javap-Tool im Sun JDK angezeigt werden.

In dem in der Frage erwähnten Fall ist das hinzugefügte/entfernte Mitglied der statische Initialisierer.Dies erscheint als ()V in Klassendateien.Der Inhalt der Methode kann mit javap -c zerlegt werden.Sie sollten den System.getProperty("foo")-Aufruf und die Zuweisung zu MYSTRING erkennen können.Allerdings wird eine Zuweisung mit einem String-Literal (oder einer beliebigen Kompilierzeitkonstante, wie in der Java-Sprachspezifikation definiert) direkt von der Klassendatei unterstützt, sodass kein statischer Initialisierer erforderlich ist.

Ein häufiger Fall für Code, der auf J2SE 1.4 (verwenden Sie -source 1.4 -target 1.4) oder früher abzielt, sind statische Felder für alte Klasseninstanzen, die als Klassenliterale im Quellcode (MyClass.class) erscheinen.Die Klasseninstanz wird bei Bedarf mit Class.forName gesucht und in einem statischen Feld gespeichert.Es ist dieses statische Feld, das die serialVersionUID stört.Ab J2SE 5.0 bietet eine Variante des LDC-Opcodes direkte Unterstützung für Klassenliterale, wodurch das synthetische Feld überflüssig wird.Auch dies kann alles mit javap -c angezeigt werden.

Wenn ich die Spezifikation richtig gelesen habe, ist die automatische serialVersionUID sollte sich nicht ändern, wenn Sie den Wert eines statischen oder transienten Felds ändern.Schauen Sie mal rein Kapitel 5.6 der Spezifikation.

Jedoch, wenn Sie ein wenig darüber nachdenken – Sie beginnen mit der Serialisierung eines Objekts, das hat static int MYINT = 3, wenn Sie dann die Klasse deserialisieren, erwarten Sie, dass Sie dasselbe Objekt zurückerhalten, d. h. mit MYINT = 3.Wenn Sie also die statische Initialisierung ändern, würden Sie Folgendes erwarten serialVersionUID ändern, weil Sie das gleiche Objekt nicht wieder zurückbekommen können.

Wie auch immer, behalten Sie dies in allen Ihren serialisierbaren Klassen bei und Sie können das steuern serialVersionUID:

private static final long serialVersionUID = 7526472295622776147L;

Ich habe die Frage aktualisiert, um sie klarer zu machen.Ich verstehe, warum die Initialisierung mit einem Literal das ändert serialVersionUID aber nicht, warum die dynamische Initialisierung es ändert.Wenn Sie mit einer Methode initialisieren, kann der Wert natürlich immer unterschiedlich sein.

Einstellen der serialVersionUID explizit ist in einer nachfolgenden Version der Klasse nur dann in Ordnung, wenn Sie sicher sind, dass es sich um eine sichere Änderung handelt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top