Mi a serialVersionUID?

1. Áttekintés

Egyszerűen fogalmazva, a serialVersionUID a. egyedi azonosítója Sorosítható osztályok.

Ezt egy objektum deszerializálása során használják annak biztosítására, hogy a betöltött osztály kompatibilis legyen a sorosított objektummal. Ha nem található megfelelő osztály, akkor egy InvalidClassException dobják.

2. Soros verzió UID

Kezdjük egy sorozható osztály létrehozásával, és deklaráljuk a serialVersionUID azonosító:

public class Az AppleProduct Serializable {private static final long serialVersionUID = 1234567L; nyilvános String headphonePort; public String ThunderboltPort; }

Ezután két segédprogram osztályra lesz szükségünk: az egyikre az AppleProduct objektum a Húr, másik pedig az objektum deszerializálását attól Húr:

public class SerializationUtility {public static void main (String [] args) {AppleProduct macBook = új AppleProduct (); macBook.headphonePort = "headphonePort2020"; macBook.thunderboltPort = "thunderboltPort2020"; String serializedObj = serializeObjectToString (macBook); System.out.println ("Sorosított AppleProduct objektum a karaktersorozathoz:"); System.out.println (serializedObj); } public static String serializeObjectToString (Serializable o) {ByteArrayOutputStream baos = new ByteArrayOutputStream (); ObjectOutputStream oos = új ObjectOutputStream (baos); oos.writeObject (o); oos.close (); adja vissza a Base64.getEncoder (). encodeToString (baos.toByteArray ()); }}
public class DeserializationUtility {public static void main (String [] args) {String serializedObj = ... // az egyértelműség kedvéért System.out.println ("AppleProduct deserializálása ..."); AppleProduct deserializedObj = (AppleProduct) deSerializeObjectFromString (serializedObj); System.out.println ("Az AppleProduct fejhallgató-portja:" + deserializedObj.getHeadphonePort ()); System.out.println ("Az AppleProduct Thunderbolt portja:" + deserializedObj.getThunderboltPort ()); } public static Object deSerializeObjectFromString (String s) IOException, ClassNotFoundException {byte [] data = Base64.getDecoder (). decode (s); ObjectInputStream ois = új ObjectInputStream (új ByteArrayInputStream (adatok)); Object o = ois.readObject (); ois.close (); visszatér o; }}

A futással kezdjük SerializationUtility.java, amely elmenti (sorosítja) a AppleProduct objektum a Húr instance, a bájtok kódolása a Base64 segítségével.

Majd ezt használva Húr a deserializációs módszer érveként futunk DeserializationUtility.java, amely újra összerakja (deserializálja) a AppleProduct tárgy az adottból Húr.

A létrehozott kimenetnek hasonlónak kell lennie ehhez:

Szerializált AppleProduct objektumot húr: rO0ABXNyACljb20uYmFlbGR1bmcuZGVzZXJpYWxpemF0aW9uLkFwcGxlUHJvZHVjdAAAAAAAEta HAgADTAANaGVhZHBob25lUG9ydHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wADmxpZ2h0ZW5pbmdQb3 J0cQB + AAFMAA90aHVuZGVyYm9sdFBvcnRxAH4AAXhwdAARaGVhZHBob25lUG9ydDIwMjBwdAATd Gh1bmRlcmJvbHRQb3J0MjAyMA ==
Az AppleProduct deserializálása ... Az Apple fejhallgató-portja Termék: headphonePort2020 Az Apple Thunderbolt-portja Termék: thunderboltPort2020

Most módosítsuk a serialVersionUIDállandóan AppleProduct.java, és újból megpróbálja deserializálni a AppleProduct ugyanabból a karakterláncból korábban előállított objektum. Újra futás DeserializationUtility.java generálnia kell ezt a kimenetet.

Az AppleProduct deserializálása ... Kivétel a "main" szálban java.io.InvalidClassException: com.baeldung.deserialization.AppleProduct; helyi osztály nem kompatibilis: stream classdesc serialVersionUID = 1234567, helyi osztály serialVersionUID = 7654321 a java.io.ObjectStreamClass.initNonProxy (ObjectStreamClass.java:616) címen a java.io.ObjectInputStream.readNonProxyDesc.objektum alatt ObjectInputStream.readClassDesc (ObjectInputStream.java:1521) itt: java.io.ObjectInputStream.readOrdinaryObject (ObjectInputStream.java:1781) a java.io.ObjectInputStream.readObject0 (ObjectInputStream.java:b53) at java. .java: 373) a com.baeldung.deserialization.DeserializationUtility.deSerializeObjectFromString (DeserializationUtility.java:24) a com.baeldung.deserialization.DeserializationUtility.main (DeserializationUtility.java:15)

A serialVersionUID osztályának verzióját / állapotát módosítottuk. Ennek eredményeként a deserializáció során nem találtak kompatibilis osztályokat, és egy InvalidClassException dobták.

3. Kompatibilis változások

Tegyük fel, hogy hozzá kell adnunk egy új mezőt villámKikötő a meglévő AppleProduct osztály:

public class Az AppleProduct megvalósítja a Serializable {// ... public String lightningPort; }

Mivel csak új mezőt adunk hozzá, nincs változás a serialVersionUID szükséges lesz. Ez azért van, mert, a deserializációs folyamat során, nulla a rendszer alapértelmezett értékként lesz hozzárendelve villámKikötő terület.

Módosítsuk a DeserializationUtility osztály az új mező értékének kinyomtatásához:

System.out.println ("Az AppleProduct LightningPort portja:" + deserializedObj.getLightningPort ());

Most, amikor újraindítottuk a DeserializationUtility osztályban hasonló kimenetet fogunk látni:

Az AppleProduct deserializálása…

4. Alapértelmezett soros verzió

Ha nem definiáljuk a serialVersionUID állam a Sorosítható osztály, akkor a Java meghatározza az egyiket az osztály bizonyos tulajdonságai alapján, például az osztály neve, a példánymezők stb.

Határozzunk meg egy egyszerűt Sorosítható osztály:

nyilvános osztály DefaultSerial implementálja a Serializable {}

Ha ennek az osztálynak egy példányát sorosítjuk, mint a következő:

DefaultSerial példány = new DefaultSerial (); System.out.println (SerializationUtility.serializeObjectToString (példány));

Ez kinyomtatja a sorosított bináris Base64 összefoglalóját:

rO0ABXNyACpjb20uYmFlbGR1bmcuZGVzZXJpYWxpemF0aW9uLkRlZmF1bHRTZXJpYWx9iVz3Lz / mdAIAAHhw

Csakúgy, mint korábban, képesnek kell lennünk arra, hogy ezt a példányt deserializáljuk az összefoglalóból:

Karaktersorozat = "rO0ABXNyACpjb20uYmFlbGR1bmcuZGVzZXJpY" + "WxpemF0aW9uLkRlZmF1bHRTZXJpYWx9iVz3Lz / mdAIAAHhw"; DefaultSerial instance = (DefaultSerial) DeserializationUtility.deSerializeObjectFromString (digest);

Ennek az osztálynak a néhány módosítása azonban megsértheti a sorosítási kompatibilitást. Például, ha hozzáadunk a magán mező ehhez az osztályhoz:

public class DefaultSerial implementálja a Serializable {private String name; }

Ezután próbálja deserializálni ugyanazt az Base64 kivonatot osztálypéldányra, kapunk egy InvalidClassException:

Kivétel a "main" szálban java.io.InvalidClassException: com.baeldung.deserialization.DefaultSerial; lokális osztály nem kompatibilis: stream classdesc serialVersionUID = 9045863543269746292, local class serialVersionUID = -2692722436255640434

Az ilyen jellegű nemkívánatos összeférhetetlenség miatt mindig jó kijelenteni a serialVersionUID ban ben Sorosítható osztályok. Így megtarthatjuk vagy továbbfejleszthetjük a verziót, ahogy maga az osztály is fejlődik.

5. Következtetés

Ebben a gyors cikkben bemutattuk a serialVersionUID állandó a sorosított adatok verziószámának megkönnyítése érdekében.

Mint mindig, a cikkben használt kódminták megtalálhatók a GitHubon.