Wat is een serialVersionUID en waarom zou ik het gebruiken?

Eclipse geeft waarschuwingen wanneer een serialVersionUIDontbreekt.

De serialiseerbare klasse Foo verklaart geen statische finale
serialVersionUID-veld van het type lang

Wat is serialVersionUIDen waarom is het belangrijk? Laat een voorbeeld zien waarbij het ontbreken van serialVersionUIDeen probleem zal veroorzaken.


Antwoord 1, autoriteit 100%

De documenten voor java.io.Serializablezijn waarschijnlijk een even goede uitleg als je zult krijgen:

De serialisatieruntime koppelt aan elke serialiseerbare klasse een versienummer, een serialVersionUIDgenaamd, dat tijdens deserialisatie wordt gebruikt om te verifiëren dat de afzender en ontvanger van een geserialiseerd object klassen voor dat object hebben geladen die compatibel met serialisatie. Als de ontvanger een klasse voor het object heeft geladen die een andere serialVersionUIDheeft dan die van de klasse van de corresponderende afzender, zal deserialisatie resulteren in een
InvalidClassException. Een serialiseerbare klasse kan zijn eigen serialVersionUIDexpliciet declareren door een veld met de naam serialVersionUIDte declareren dat statisch, definitief en van het type longmoet zijn:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

Als een serialiseerbare klasse niet expliciet een serialVersionUIDdeclareert, berekent de serialisatieruntime een standaard serialVersionUID-waarde voor die klasse op basis van verschillende aspecten van de klasse, zoals beschreven in de Java(TM) Object Serialization Specification. Het wordt echter sterk aanbevolendat alle serialiseerbare klassen expliciet serialVersionUID-waarden declareren, aangezien de standaardberekening van serialVersionUIDzeer gevoelig is voor klassedetails die kunnen variëren. afhankelijk van de implementaties van de compiler, en kan dus resulteren in onverwachte InvalidClassExceptionstijdens deserialisatie. Om een ​​consistente serialVersionUID-waarde te garanderen voor verschillende Java-compilerimplementaties, moet een serialiseerbare klasse daarom een ​​expliciete serialVersionUID-waarde declareren. Het wordt ook sterk aangeraden dat expliciete serialVersionUID-declaraties waar mogelijk de private modifier gebruiken, aangezien dergelijke declaraties alleen van toepassing zijn op de onmiddellijk declarerende klasse serialVersionUID-velden zijn niet nuttig als overgeërfde leden.


Antwoord 2, autoriteit 20%

Als je serialiseert alleen maar omdat je moet serialiseren omwille van de implementatie (wat maakt het uit of je serialiseert voor een HttpSession, bijvoorbeeld… als het is opgeslagen of niet, doe je dat waarschijnlijk niet’ als u zich zorgen maakt over het de-serializingvan een formulierobject), dan kunt u dit negeren.

Als je daadwerkelijk serialisatie gebruikt, is het alleen van belang als je van plan bent om objecten rechtstreeks op te slaan en op te halen met behulp van serialisatie. De serialVersionUIDvertegenwoordigt de versie van uw klas, en u moet deze verhogen als de huidige versie van uw klas niet achterwaarts compatibel is met de vorige versie.

Meestal zult u serialisatie waarschijnlijk niet rechtstreeks gebruiken. Als dit het geval is, genereert u een standaard serialVersionUIDdoor op de quick fix-optie te klikken en maakt u zich er geen zorgen over.


Antwoord 3, autoriteit 13%

Ik kan deze kans niet voorbij laten gaan om het boek van Josh Bloch Effectieve Java(2e editie). Hoofdstuk 11 is een onmisbare bron over Java-serialisatie.

Per Josh wordt de automatisch gegenereerde UID gegenereerd op basis van een klassenaam, geïmplementeerde interfaces en alle openbare en beschermde leden. Als u deze op enigerlei wijze wijzigt, wordt de serialVersionUIDgewijzigd. U hoeft er dus niet mee te rommelen als u er zeker van bent dat er nooit meer dan één versie van de klasse zal worden geserialiseerd (over processen heen of op een later tijdstip uit de opslag wordt opgehaald).

Als je ze voor nu negeert en later ontdekt dat je de klasse op de een of andere manier moet veranderen, maar de compatibiliteit met de oude versie van de klasse moet behouden, kun je de JDK-tool serialvergebruiken om de serialVersionUIDop de oudeklasse, en stel die expliciet in op de nieuwe klasse. (Afhankelijk van uw wijzigingen moet u mogelijk ook aangepaste serialisatie implementeren door de methoden writeObjecten readObjecttoe te voegen – zie Serializablejavadoc of eerder hoofdstuk 11.)


Antwoord 4, autoriteit 6%

Je kunt Eclipse vertellen deze serialVersionUID-waarschuwingen te negeren:

Venster > Voorkeuren > Java > Samensteller > Fouten/waarschuwingen > Potentiële programmeerproblemen

Voor het geval je het nog niet wist, er zijn een heleboel andere waarschuwingen die je in deze sectie kunt inschakelen (of sommige zelfs als fouten kunt laten rapporteren), vele zijn erg handig:

  • Potentiële programmeerproblemen: mogelijk onbedoelde booleaanse toewijzing
  • Potentiële programmeerproblemen: null-pointertoegang
  • Onnodige code: lokale variabele wordt nooit gelezen
  • Onnodige code: overbodige nulcontrole
  • Onnodige code: Onnodige cast of ‘instanceof’

en nog veel meer.


Antwoord 5, autoriteit 5%

serialVersionUIDmaakt versiebeheer van geserialiseerde gegevens mogelijk. De waarde ervan wordt opgeslagen met de gegevens bij het serialiseren. Bij het de-serialiseren wordt dezelfde versie gecontroleerd om te zien hoe de geserialiseerde gegevens overeenkomen met de huidige code.

Als je een versie van je gegevens wilt, begin je normaal gesproken met een serialVersionUIDvan 0, en stoot je deze aan bij elke structurele wijziging in je klasse die de geserialiseerde gegevens verandert (toevoegen of verwijderen van niet-tijdelijke velden ).

Het ingebouwde de-serialiseringsmechanisme (in.defaultReadObject()) zal weigeren om oude versies van de gegevens te de-serialiseren. Maar als je wilt, kun je je eigen readObject()-functie die oude gegevens kan teruglezen. Deze aangepaste code kan vervolgens de serialVersionUIDcontroleren om te weten in welke versie de gegevens zich bevinden en om te beslissen hoe deze de-serialiseren. Deze techniek voor versiebeheer is handig als u geserialiseerde gegevens opslaat die verschillende versies van uw code overleven.

Maar het opslaan van geserialiseerde gegevens voor zo’n lange tijdspanne is niet erg gebruikelijk. Het is veel gebruikelijker om het serialisatiemechanisme te gebruiken om tijdelijk gegevens naar bijvoorbeeld een cache te schrijven of deze via het netwerk naar een ander programma te sturen met dezelfde versie van de relevante delen van de codebase.

In dit geval bent u niet geïnteresseerd in het handhaven van achterwaartse compatibiliteit. Je bent alleen bezig om ervoor te zorgen dat de codebases die communiceren inderdaad dezelfde versies van relevante klassen hebben. Om een ​​dergelijke controle te vergemakkelijken, moet u de serialVersionUIDnet als voorheen onderhouden en niet vergeten deze bij te werken wanneer u wijzigingen aanbrengt in uw klassen.

Als u vergeet het veld bij te werken, krijgt u mogelijk twee verschillende versies van een klasse met een verschillende structuur, maar met dezelfde serialVersionUID. Als dit gebeurt, zal het standaardmechanisme (in.defaultReadObject()) geen verschil detecteren en proberen incompatibele gegevens te deserialiseren. Nu kunt u eindigen met een cryptische runtime-fout of een stille storing (null-velden). Dit soort fouten kan moeilijk te vinden zijn.

Dus om deze usecase te helpen, biedt het Java-platform u de keuze om de serialVersionUIDniet handmatig in te stellen. In plaats daarvan wordt tijdens het compileren een hash van de klassenstructuur gegenereerd en als id gebruikt. Dit mechanisme zorgt ervoor dat u nooit verschillende klassenstructuren met dezelfde id hebt, en u krijgt dus niet de hierboven genoemde moeilijk te traceren runtime-serialisatiefouten.

Maar er is een keerzijde aan de automatisch gegenereerde ID-strategie. Namelijk dat de gegenereerde id’s voor dezelfde klasse kunnen verschillen tussen compilers (zoals hierboven vermeld door Jon Skeet). Dus als u geserialiseerde gegevens communiceert tussen code die is gecompileerd met verschillende compilers, is het raadzaam om de id’s toch handmatig te onderhouden.

En als u achterwaarts compatibel bent met uw gegevens, zoals in de eerste genoemde use-case, wilt u waarschijnlijk ook de id zelf onderhouden. Dit om leesbare ID’s te krijgen en meer controle te hebben over wanneer en hoe ze veranderen.


Antwoord 6, autoriteit 3%

Wat is een serialVersionUIDen waarom zou ik het gebruiken?

serialVersionUIDis een unieke identificator voor elke klasse, JVMgebruikt deze om de versies van de klasse te vergelijken en ervoor te zorgen dat dezelfde klasse werd gebruikt tijdens serialisatie en tijdens deserialisatie wordt geladen.

Als u er een opgeeft, krijgt u meer controle, hoewel JVM er een genereert als u dit niet opgeeft. De gegenereerde waarde kan verschillen tussen verschillende compilers. Bovendien wil je soms om de een of andere reden deserialisatie van oude geserialiseerde objecten [backward incompatibility] verbieden, en in dit geval moet je gewoon de serialVersionUID wijzigen.

De javadocs voor Serializablezeg:

de standaard serialVersionUID-berekening is zeer gevoelig voor klasse
details die kunnen variëren afhankelijk van de implementatie van de compiler, en kunnen
resulteren dus in onverwachte InvalidClassExceptions tijdens
deserialisatie.

Daarom moet u serialVersionUID declareren omdat dit ons meer controle geeft.

Dit artikelbevat een aantal goede punten over het onderwerp.


Antwoord 7, autoriteit 3%

Oorspronkelijke vraag was ‘waarom is het belangrijk’ en ‘voorbeeld’ waar deze Serial Version IDnuttig zou zijn. Nou, ik heb er een gevonden.

Stel dat u een klasse Carmaakt, deze instantiseert en naar een objectstroom schrijft. Het afgeplatte auto-object zit enige tijd in het bestandssysteem. Ondertussen, als de klasse Carwordt gewijzigd door een nieuw veld toe te voegen. Later, wanneer u het afgeplatte Car-object probeert te lezen (dwz deserialiseren), krijgt u de java.io.InvalidClassException omdat alle serialiseerbare klassen automatisch een unieke identificatie krijgen . Deze uitzondering wordt gegenereerd wanneer de identifier van de klasse niet gelijk is aan de identifier van het afgeplatte object. Als je er echt over nadenkt, wordt de uitzondering gegooid vanwege de toevoeging van het nieuwe veld. U kunt voorkomen dat deze uitzondering wordt gegenereerd door het versiebeheer zelf te beheren door een expliciete serialVersionUID te declareren. Er is ook een klein prestatievoordeel bij het expliciet declareren van uw serialVersionUID(omdat dit niet hoeft te worden berekend). Het is dus het beste om uw eigen serialVersionUID aan uw serializable-klassen toe te voegen zodra u ze maakt, zoals hieronder wordt weergegeven:

public class Car {
    static final long serialVersionUID = 1L; //assign a long value
}

Antwoord 8, autoriteit 2%

Eerst moet ik uitleggen wat serialisatie is.

Serialisatiemaakt het mogelijk om een ​​object naar een stream te converteren, om dat object over het netwerk te verzenden OF Opslaan in bestand OF opslaan in DB voor gebruik in letters.

Er zijn enkele regels voor serialisatie.

  • Een object is alleen serialiseerbaar als zijn klasse of superklasse de Serializable-interface implementeert

  • Een object is serialiseerbaar (zelf implementeert de Serializable-interface), zelfs als zijn superklasse dat niet is. De eerste superklasse in de hiërarchie van de serialiseerbare klasse, die geen Serializable-interface implementeert, MOET echter een no-arg-constructor hebben. Als dit wordt geschonden, produceert readObject() een java.io.InvalidClassException tijdens runtime

  • Alle primitieve typen zijn serialiseerbaar.

  • Tijdelijke velden (met tijdelijke modificatie) zijn NIET geserialiseerd (d.w.z. niet opgeslagen of hersteld). Een klasse die Serializable implementeert, moet tijdelijke velden markeren van klassen die geen serialisatie ondersteunen (bijvoorbeeld een bestandsstroom).

  • Statische velden (met statische modifier) ​​zijn niet geserialiseerd.

Als Objectgeserialiseerd is, koppelt Java Runtime het serieversienummer oftewel de serialVersionID.

Waar we serialVersionID nodig hebben:

Tijdens de deserialisatie om te controleren of zender en ontvanger compatibel zijn met betrekking tot serialisatie. Als de ontvanger de klasse heeft geladen met een andere serialVersionID, eindigt de deserialisatie met InvalidClassCastException.
Een serialiseerbare klasse kan zijn eigen serialVersionUIDexpliciet declareren door een veld met de naam serialVersionUIDte declareren dat statisch, definitief en van het type lang moet zijn.

Laten we dit met een voorbeeld proberen.

import java.io.Serializable;
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    private String empname;
    private byte empage;
    public String getEmpName() {
        return name;
    }
    public void setEmpName(String empname) {
        this.empname = empname;
    }
    public byte getEmpAge() {
        return empage;
    }
    public void setEmpAge(byte empage) {
        this.empage = empage;
    }
    public String whoIsThis() {
        return getEmpName() + " is " + getEmpAge() + "years old";
    }
}

Maak een serieel object

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Writer {
    public static void main(String[] args) throws IOException {
        Employee employee = new Employee();
        employee.setEmpName("Jagdish");
        employee.setEmpAge((byte) 30);
        FileOutputStream fout = new
                FileOutputStream("/users/Jagdish.vala/employee.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fout);
        oos.writeObject(employee);
        oos.close();
        System.out.println("Process complete");
    }
}

Deserialiseer het object

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Reader {
    public static void main(String[] args) throws ClassNotFoundException, IOException {
        Employee employee = new Employee();
        FileInputStream fin = new FileInputStream("/users/Jagdish.vala/employee.obj");
        ObjectInputStream ois = new ObjectInputStream(fin);
        employee = (Employee) ois.readObject();
        ois.close();
        System.out.println(employee.whoIsThis());
    }
}

OPMERKING: Wijzig nu de serialVersionUID van de klasse Employee en sla op:

private static final long serialVersionUID = 4L;

En voer de Reader-klasse uit. Als u de klasse Writer niet uitvoert, krijgt u de uitzondering.

Exception in thread "main" java.io.InvalidClassException: 
com.jagdish.vala.java.serialVersion.Employee; local class incompatible: 
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)

Antwoord 9, autoriteit 2%

Als u uw objecten nooit naar byte-array hoeft te serialiseren en ze te verzenden/opslaan, hoeft u zich daar geen zorgen over te maken. Als u dat doet, moet u rekening houden met uw serialVersionUID, aangezien de deserializer van het object het zal matchen met de versie van het object dat zijn classloader heeft. Lees er meer over in de Java-taalspecificatie.


Antwoord 10

Als je deze waarschuwing krijgt voor een klasse waar je nooit aan denkt om te serialiseren, en waarvan je niet hebt verklaard dat je implements Serializable, komt dat vaak omdat je geërfd hebt van een superklasse, die implementeert serialiseerbaar. Vaak is het dan beter om aan zo’n object te delegeren in plaats van overerving te gebruiken.

Dus, in plaats van

public class MyExample extends ArrayList<String> {
    public MyExample() {
        super();
    }
    ...
}

doen

public class MyExample {
    private List<String> myList;
    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

en roep in de relevante methoden myList.foo()aan in plaats van this.foo()(of super.foo()) . (Dit past niet in alle gevallen, maar toch vrij vaak.)

Ik zie vaak mensen JFrame of iets dergelijks uitbreiden, terwijl ze dit eigenlijk alleen maar hoeven te delegeren. (Dit helpt ook bij het automatisch aanvullen in een IDE, aangezien JFrame honderden methoden heeft, die je niet nodig hebt als je je aangepaste methoden in je klas wilt aanroepen.)

Een geval waarin de waarschuwing (of de serialVersionUID) onvermijdelijk is, is wanneer u uitbreidt vanuit AbstractAction, normaal gesproken in een anonieme klasse, en alleen de actionPerformed-methode toevoegt. Ik denk dat er in dit geval geen waarschuwing zou moeten zijn (aangezien je dergelijke anonieme klassen normaal gesproken toch niet betrouwbaar kunt serialiseren en deserialiseren in verschillende versies van je klasse), maar ik weet niet zeker hoe de compiler dit zou kunnen herkennen.


Antwoord 11

Om de betekenis van veld serialVersionUID te begrijpen, moet men begrijpen hoe serialisatie/deserialisatie werkt.

Als een Serializable-klasseobject geserialiseerd is, koppelt Java Runtime een serieel versienummer (serialVersionUID) aan dit geserialiseerde object. Op het moment dat u dit geserialiseerde object deserialiseert, komt Java Runtime overeen met de serialVersionUID van het geserialiseerde object met de serialVersionUID van de klasse. Als beide gelijk zijn, gaat het alleen verder met het verdere proces van deserialisatie, anders wordt InvalidClassException gegenereerd.

Dus we concluderen dat om het serialisatie-/deserialisatieproces te laten slagen, de serialVersionUID van het geserialiseerde object gelijk moet zijn aan de serialVersionUID van de klasse. Als de programmeur de serialVersionUID-waarde expliciet in het programma specificeert, wordt dezelfde waarde geassocieerd met het geserialiseerde object en de klasse, ongeacht het serialisatie- en deserialiseringsplatform (serialisering kan bijvoorbeeld worden gedaan op platformachtige Windows met behulp van sun of MS JVM en Deserialisatie bevinden zich mogelijk op een ander Linux-platform met Zing JVM).

Maar als serialVersionUID niet is opgegeven door de programmeur, dan gebruikt Java runtime tijdens het uitvoeren van Serialization\DeSerialization van een object zijn eigen algoritme om het te berekenen. Dit serialVersionUID-berekeningsalgoritme varieert van JRE tot JRE. Het is ook mogelijk dat de omgeving waarin het object is geserialiseerd één JRE gebruikt (bijv. SUN JVM) en dat de omgeving waar deserialisering plaatsvindt Linux Jvm(zing) gebruikt. In dergelijke gevallen zal de serialVersionUID die is gekoppeld aan het geserialiseerde object anders zijn dan de serialVersionUID van de klasse die is berekend in de deserialiseringsomgeving. Op zijn beurt zal deserialisatie niet succesvol zijn. Dus om dergelijke situaties/problemen te voorkomen, moet de programmeur altijd de serialVersionUID van de Serializable-klasse specificeren.


Antwoord 12

Als voorbeeld waarbij de ontbrekende serialVersionUID een probleem kan veroorzaken:

Ik werk aan deze Java EE-toepassing die is samengesteld uit een webmodule die gebruikmaakt van een EJB-module. De webmodule roept de EJB-module op afstand aan en geeft een POJO'sdoor die Serializableals argument implementeert.

De klasse van deze POJO'swas verpakt in de EJB-pot en in zijn eigen pot in de WEB-INF/lib van de webmodule. Ze zijn eigenlijk van dezelfde klasse, maar wanneer ik de EJB-module inpak, pak ik de pot van deze POJO uit om hem samen met de EJB-module in te pakken.

De aanroep naar de EJBmislukte met de onderstaande Uitzondering omdat ik de serialVersionUIDniet had aangegeven:

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52

Antwoord 13

Doe geen moeite, de standaardberekening is erg goed en voldoet in 99,9999% van de gevallen. En als je problemen tegenkomt, kun je – zoals al gezegd – UID’s invoeren als dat nodig is (wat hoogst onwaarschijnlijk is)


Antwoord 14

Ik gebruik over het algemeen serialVersionUIDin één context: als ik weet dat het de context van de Java VM verlaat.

Ik zou dit weten als ik ObjectInputStreamen ObjectOutputStreamvoor mijn applicatie gebruik of als ik weet dat een bibliotheek/framework dat ik gebruik het zal gebruiken. De serialVersionID zorgt ervoor dat verschillende Java-VM’s van verschillende versies of leveranciers correct samenwerken, of als het wordt opgeslagen en opgehaald buiten de VM, bijvoorbeeld HttpSession, kunnen de sessiegegevens behouden blijven, zelfs tijdens een herstart en upgrade van de applicatie server.

Voor alle andere gevallen gebruik ik

@SuppressWarnings("serial")

sinds de meeste tijd is de standaard serialVersionUIDvoldoende. Dit omvat Exception, HttpServlet.


Antwoord 15

Veldgegevens vertegenwoordigen bepaalde informatie die in de klas is opgeslagen.
Class implementeert de Serializableinterface,
dus eclipse wordt automatisch aangeboden om het veld serialVersionUIDte declareren. Laten we beginnen met waarde 1 daar ingesteld.

Als je niet wilt dat die waarschuwing komt, gebruik dan dit:

@SuppressWarnings("serial")

Antwoord 16

SerialVersionUID wordt gebruikt voor versiebeheer van het object. u kunt ook serialVersionUID in uw klassenbestand opgeven. Het gevolg van het niet specificeren van serialVersionUID is dat wanneer u een veld in de klasse toevoegt of wijzigt, de reeds geserialiseerde klasse niet kan herstellen omdat de seriëleVersionUID gegenereerd voor de nieuwe klasse en voor het oude geserialiseerde object anders zal zijn. Het Java-serialisatieproces is afhankelijk van de juiste serialVersionUID voor het herstellen van de status van het geserialiseerde object en genereert java.io.InvalidClassException in het geval van een niet-overeenkomende serialVersionUID

Lees meer: ​​http://javarevisited.blogspot.com/ 2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ


Antwoord 17

Het zou mooi zijn als CheckStyle kon verifiëren dat de serialVersionUID op een klasse die Serializable implementeert een goede waarde heeft, d.w.z. dat het overeenkomt met wat de seriële versie-id-generator zou produceren. Als je een project hebt met veel serialiseerbare DTO’s, bijvoorbeeld, onthouden om de bestaande serialVersionUID te verwijderen en opnieuw te genereren, is lastig, en momenteel is de enige manier (die ik ken) om dit te verifiëren door voor elke klasse opnieuw te genereren en te vergelijken met de oude. Dit is heel erg pijnlijk.


Antwoord 18

Waarom serialVersionUIDgebruiken in de klasse Serializablein Java?

Tijdens serializationmaakt Java-runtime een versienummer voor een klasse, zodat deze deze later kan de-serialiseren. Dit versienummer staat bekend als serialVersionUIDin Java.

serialVersionUIDwordt gebruikt om geserialiseerde gegevens te versies. U kunt een klasse alleen de-serialiseren als deze serialVersionUIDovereenkomt met de geserialiseerde instantie. Wanneer we serialVersionUIDniet declareren in onze klasse, genereert Java runtime het voor ons, maar het wordt niet aanbevolen. Het wordt aanbevolen om serialVersionUIDte declareren als private static final longvariabele om het standaardmechanisme te vermijden.

Wanneer u een klasse declareert als Serializabledoor de markerinterface java.io.Serializablete implementeren, blijft Java runtime-instantie van die klasse op schijf door gebruik te maken van het standaard serialisatiemechanisme, mits je hebt het proces niet aangepast met de Externalizableinterface.

zie ook Waarom gebruik SerialVersionUID binnen de klasse Serializable in Java


Antwoord 19

Als je een groot aantal klassen wilt wijzigen waarvoor in de eerste plaats geen serialVersionUID was ingesteld, terwijl je de compatibiliteit met de oude klassen wilt behouden, schieten tools zoals IntelliJ Idea, Eclipse tekort omdat ze willekeurige getallen genereren en niet werken op een stapel bestanden in één keer. Ik kom op het volgende bash-script (het spijt me voor Windows-gebruikers, overweeg een Mac te kopen of om te zetten naar Linux) om het serialVersionUID-probleem gemakkelijk te wijzigen:

base_dir=$(pwd)                                                                  
src_dir=$base_dir/src/main/java                                                  
ic_api_cp=$base_dir/target/classes                                               
while read f                                                                     
do                                                                               
    clazz=${f//\//.}                                                             
    clazz=${clazz/%.java/}                                                       
    seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//')
    perl -ni.bak -e "print $_; printf qq{%s\n}, q{    private $seruidstr} if /public class/" $src_dir/$f
done

je slaat dit script op, zeg add_serialVersionUID.sh naar jou ~/bin. Vervolgens voer je het uit in de hoofdmap van je Maven- of Gradle-project, zoals:

add_serialVersionUID.sh < myJavaToAmend.lst

Deze .lst bevat de lijst met java-bestanden om de serialVersionUID in de volgende indeling toe te voegen:

com/abc/ic/api/model/domain/item/BizOrderTransDO.java
com/abc/ic/api/model/domain/item/CardPassFeature.java
com/abc/ic/api/model/domain/item/CategoryFeature.java
com/abc/ic/api/model/domain/item/GoodsFeature.java
com/abc/ic/api/model/domain/item/ItemFeature.java
com/abc/ic/api/model/domain/item/ItemPicUrls.java
com/abc/ic/api/model/domain/item/ItemSkuDO.java
com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java
com/abc/ic/api/model/domain/serve/ServeFeature.java
com/abc/ic/api/model/param/depot/DepotItemDTO.java
com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java
com/abc/ic/api/model/param/depot/InDepotDTO.java
com/abc/ic/api/model/param/depot/OutDepotDTO.java

Dit script gebruikt de JDK serialVer-tool onder de motorkap. Zorg er dus voor dat je $JAVA_HOME/bin in het PATH staat.


Antwoord 20

Deze vraag is zeer goed gedocumenteerd in Effective Java door Joshua Bloch. Een heel goed boek en een aanrader om te lezen. Ik zal hieronder enkele van de redenen uiteenzetten:

De serialisatie-runtime komt met een nummer met de naam Seriële versie voor elke serialiseerbare klasse. Dit nummer wordt serialVersionUID genoemd. Nu zit er wat wiskunde achter dit nummer en het komt uit op basis van de velden / methoden die in de klas zijn gedefinieerd. Voor dezelfde klasse wordt elke keer dezelfde versie gegenereerd. Dit nummer wordt gebruikt tijdens deserialisatie om te controleren of de afzender en ontvanger van een geserialiseerd object klassen voor dat object hebben geladen die compatibel zijn met betrekking tot serialisatie. Als de ontvanger een klasse voor het object heeft geladen die een andere serialVersionUID heeft dan die van de klasse van de corresponderende afzender, zal deserialisatie resulteren in een InvalidClassException.

Als de klasse serializeerbaar is, kunt u ook uw eigen serialVersionUID expliciet declareren door een veld met de naam “serialVersionUID” te declareren dat statisch, definitief en van het type lang moet zijn. De meeste IDE’s zoals Eclipse helpen je om die lange string te genereren.


Antwoord 21

Een eenvoudige uitleg:

  1. Brengt u gegevens aan het serialiseren?

    Serialisatie is in feite het schrijven van klassegegevens naar een bestand/stream/etc. De-serialisatie leest die gegevens terug naar een klas.

  2. Ben je van plan om in productie te gaan?

    Als je gewoon iets test met onbelangrijke/nepgegevens, maak je er dan geen zorgen over (tenzij je de serialisatie rechtstreeks test).

  3. Is dit de eerste versie?

    Zo ja, stel serialVersionUID=1Lin.

  4. Is dit de tweede, derde, etc. productversie?

    Nu moet u zich zorgen maken over serialVersionUIDen moet u dit grondig onderzoeken.

Als je de versie niet correct bijwerkt wanneer je een les bijwerkt die je moet schrijven/lezen, krijg je een foutmelding wanneer je oude gegevens probeert te lezen.


Antwoord 22

‘serialVersionUID’ is een 64-bits nummer dat wordt gebruikt om een ​​klasse op unieke wijze te identificeren tijdens het deserialisatieproces. Wanneer u een object serialiseert, wordt serialVersionUID van de klasse ook naar het bestand geschreven. Telkens wanneer u dit object deserialiseert, extraheert Java runtime deze serialVersionUID-waarde uit de geserialiseerde gegevens en vergelijkt u dezelfde waarde die is gekoppeld aan de klasse. Als beide niet overeenkomen, wordt ‘java.io.InvalidClassException’ gegenereerd.

Als een serialiseerbare klasse niet expliciet een serialVersionUID declareert, berekent de serialisatie-runtime de serialVersionUID-waarde voor die klasse op basis van verschillende aspecten van de klasse, zoals velden, methoden, enz., U kunt dit linkvoor demo-applicatie.


Antwoord 23

Om een ​​lang verhaal kort te maken, wordt dit veld gebruikt om te controleren of geserialiseerde gegevens correct kunnen worden gedeserialiseerd. Serialisatie en deserialisatie worden vaak gemaakt door verschillende programmakopieën – de server converteert bijvoorbeeld object naar string en client converteert ontvangen string naar object. Dit veld vertelt dat beide werken met hetzelfde idee over wat dit object is. Dit veld helpt wanneer:

  • je hebt veel verschillende exemplaren van je programma op verschillende plaatsen (zoals 1 server en 100 clients). Als u uw object wijzigt, uw versienummer wijzigt en vergeet een van deze clients bij te werken, weet deze dat hij niet in staat is tot deserialisatie

  • je hebt je gegevens in een bestand opgeslagen en later probeer je het te openen met een bijgewerkte versie van je programma met een aangepast object – je zult weten dat dit bestand niet compatibel is als je je versie goed houdt

Wanneer is het belangrijk?

Het meest voor de hand liggend – als u enkele velden aan uw object toevoegt, kunnen oudere versies deze niet gebruiken omdat ze deze velden niet in hun objectstructuur hebben.

Minder voor de hand liggend – Wanneer u een object deserialiseert, worden velden die niet aanwezig waren in string als NULL behouden. Als je het veld uit je object hebt verwijderd, zullen oudere versies dit veld altijd-NULL houden, wat kan leiden tot wangedrag als oudere versies vertrouwen op gegevens in dit veld (je hebt het hoe dan ook voor iets gemaakt, niet alleen voor de lol 🙂 )

Minst voor de hand liggend – Soms verander je het idee dat je in de betekenis van een veld zet. Als je bijvoorbeeld 12 jaar oud bent, bedoel je ‘fiets’ onder ‘fiets’, maar als je 18 bent, bedoel je ‘motorfiets’ – als je vrienden je uitnodigen voor ‘fietsen door de stad’ en jij de enige bent die op de fiets kwam, zul je begrijpen hoe belangrijk het is om dezelfde betekenis over velden heen te behouden 🙂


Antwoord 24

Ten eerste om uw vraag te beantwoorden: wanneer we SerialVersionUID niet in onze klasse declareren, genereert Java runtime het voor ons, maar dat proces is gevoelig voor veel klassemetagegevens, waaronder het aantal velden, het type velden, de toegangsmodificator van velden , interface geïmplementeerd door klasse enz. Daarom wordt aanbevolen om het zelf te declareren en Eclipse waarschuwt u hiervoor.

Serialisatie:
We werken vaak met belangrijke objecten waarvan de status (gegevens in de variabelen van het object) zo belangrijk zijn dat we niet het risico kunnen lopen deze te verliezen door stroom-/systeemstoringen (of) netwerkstoringen in het geval dat de objectstatus naar een andere machine wordt verzonden. De oplossing voor dit probleem heet “Persistence”, wat simpelweg betekent dat de gegevens worden bewaard (vasthouden/opslaan). Serialisatie is een van de vele andere manieren om persistentie te bereiken (door gegevens op schijf/geheugen op te slaan). Bij het opslaan van de staat van het object is het belangrijk om een ​​identiteit voor het object aan te maken, om het goed terug te kunnen lezen (deserialisatie). Deze unieke identificatie is ID is SerialVersionUID.


Antwoord 25

Wat is SerialVersionUID?
Antwoord: – Laten we zeggen dat er twee personen zijn, een van het hoofdkwartier en een ander van ODC, die beide respectievelijk serialisatie en deserialisatie gaan uitvoeren. In dit geval om te verifiëren dat de ontvanger die zich in ODC bevindt de geverifieerde persoon is, maakt JVM een unieke ID aan die bekend staat als SerialVersionUID.

Hier is een mooie uitleg op basis van het scenario,

Waarom SerialVersionUID?

Serialisatie: op het moment van serialisatie slaat JVM bij elke objectafzender een unieke identificatie op. JVM is verantwoordelijk voor het genereren van die unieke ID op basis van het corresponderende .class-bestand dat aanwezig is in het afzendersysteem.

Deserialisatie: op het moment van deserialisatie zal JVM aan de ontvangerzijde de unieke ID die is gekoppeld aan het object vergelijken met de unieke ID van de lokale klasse, dwz JVM zal ook een unieke ID maken op basis van het overeenkomstige .class-bestand die aanwezig is in het ontvangstsysteem. Als beide unieke ID’s overeenkomen, wordt alleen deserialisatie uitgevoerd. Anders krijgen we Runtime Exception met de melding InvalidClassException. Deze unieke ID is niets anders dan SerialVersionUID

LEAVE A REPLY

Please enter your comment!
Please enter your name here

fifteen − nine =

Other episodes