Wanneer moet ik de serialVersionUID wijzigen?

Ik weet dat ik serialVersionUID kan gebruiken om de versie van klassen te beheren. En ik heb gelezen dat ik dan velden kan toevoegen of verwijderen en de klasse zal nog steeds compatibel zijn, het zal alleen standaardwaarden gebruiken.

Wanneer moetik de serialVersionUID wijzigen?


Antwoord 1, autoriteit 100%

De waarde van het veld serialVersionUID moet idealiter worden gewijzigd wanneer incompatibele wijzigingen worden aangebracht in de structuur van de klasse. De volledige lijst met incompatibele wijzigingen is aanwezig
in de Java Object Seriization-specificatie.

Om verder uit te breiden, zullen incompatibele wijzigingen aan een klasse voorkomen dat het deserialisatiemechanisme een instantie van het object maakt, omdat er informatie in de stream is die niet overeenkomt met de huidige klassedefinitie.


Antwoord 2, autoriteit 49%

De vaak herhaalde mantra over het veranderen van de serialVersionUIDelke keer dat je de klasse verandert, is compleet en volslagen onzin. Zie dit Sun-artikeldat zij opnieuw gepubliceerd op hun site en die na de overname werd gemigreerd naar het Oracle Technology Network.

Je moet de serialVersionUIDalleenwijzigen als je opzettelijk de compatibiliteit met alle bestaande serialisaties wilt verbreken, of als je wijzigingen aan de klasse zo radicaal zijn dat je geen keus hebt – in dat geval moet je echt meerdere keren nadenken over wat je eigenlijk aan het doen bent.

In alle andere gevallen moet u uw ketel kapot maken door aangepaste readObject()/writeObject()en/of writeReplace()/readResolve()methoden en/of of serialFieldsannotaties zodat u objecten uit die bestaande serialisaties kunt blijven lezen. Als je dat eenmaal doorbreekt, krijg je een grote hoofdpijn, inderdaad een nachtmerrie.


Antwoord 3, autoriteit 12%

Als u geen veld serialVersionUIDopgeeft in uw Serializable-klassen, zal de Java-compiler er een voor u specificeren — in wezen is het een hash van de klassenaam, interfacenamen, methoden en velden van de klasse. Methoden kunnen echter op elk moment worden gewijzigd, dus als u wilt wijzigen hoe een opgeslagen klasse wordt gedeserialiseerd, kunt u de methode readObject overschrijven. Als u echter het veld serialVersionUIDin uw code opgeeft, zal de compiler dat niet negeren, zelfs als u incompatibele wijzigingen aanbrengt, wat kan resulteren in een uitzondering tijdens runtime – uw IDE of compiler geeft u geen waarschuwing. (EDIT — bedankt EJP)IDE’s zoals Eclipse kunnen de UID van de compiler voor u invoegen, als u gemakkelijk wilt controleren hoe de compiler bepaalde wijzigingen bekijkt.

Als je vaak wijzigingen aanbrengt, bewaar dan een oude versie van het schijfbestand om deserialisatie mee te testen. Je kunt eenheidstests schrijven om te proberen het oude bestand in te lezen en te kijken of het werkt of dat het totaal incompatibel is.

Eén waarschuwing: ik heb persoonlijk de pijn ervaren van het werken met Serializable-klassen die oorspronkelijk bedoeld waren voor langdurige opslag en die niet goed waren ontworpen. Bijvoorbeeld het opslaan van GUI-elementen op schijf in plaats van ze te maken wanneer dat nodig is. Vraag uzelf af of Serializableecht de beste manier is om uw gegevens op te slaan.


Antwoord 4, autoriteit 5%

Voor de volledigheid is hier een lijst met wijzigingen die de compatibiliteit van Java-serialisatie verbreken volgens de java 8 spec:

  • Velden verwijderen
  • Klassen omhoog of omlaag verplaatsen in de hiërarchie
  • Een niet-statisch veld wijzigen in statisch of een niet-transiënt veld in transiënt
  • Het gedeclareerde type van een primitief veld wijzigen
  • De methode writeObject of readObject wijzigen zodat deze niet langer de standaard veldgegevens schrijft of leest, of de methode wijzigen zodat deze probeert deze te schrijven of te lezen terwijl de vorige versie dat niet deed.
  • Een klas wijzigen van Serializable naar Externalizable of vice versa
  • Een klasse wijzigen van een niet-enum-type in een enum-type of omgekeerd
  • Serializable of Externalizable verwijderen
  • De methode writeReplace of readResolve aan een klasse toevoegen

Antwoord 5

U kunt serialiVersionUID op dezelfde waarde instellen voor de levensduur van de klasse. (Niet altijd een goed idee) Opmerking: u kunt uw eigen versiecontrolestrategie voor serialisatie implementeren met readObject/writeObject als u dit nodig hebt en de UID ongewijzigd laten.

De enige keer dat u dit MOET wijzigen, is als u al enkele gegevens naar een bestand hebt geserialiseerd en u het wilt lezen. Als het om welke reden dan ook is gewijzigd, MOET u de serialiVersionUID instellen op de versie in het bestand om enige hoop te hebben dat u de gegevens kunt lezen.


Antwoord 6

Als u uw eigen serialVersionUID in java wilt declareren, typt u dit in de
geserialiseerde objectklasse:

@Serial

private statische laatste lange serialVersionUID = gewenst_nummer;

Other episodes