Čo je serialVersionUID?

1. Prehľad

Jednoducho povedané, the serialVersionUID je jedinečný identifikátor pre Serializovateľné triedy.

Toto sa používa počas deserializácie objektu, aby sa zabezpečilo, že načítaná trieda je kompatibilná so serializovaným objektom. Ak sa nenájde žiadna zodpovedajúca trieda, an InvalidClassException je hodená.

2. UID sériovej verzie

Začnime vytvorením serializovateľnej triedy a vyhlásime a serialVersionUID identifikátor:

verejná trieda AppleProduct implementuje Serializable {private static final long serialVersionUID = 1234567L; verejný String headphonePort; verejný String thunderboltPort; }

Ďalej budeme potrebovať dve triedy nástrojov: jednu na serializáciu súboru AppleProduct objekt do a Reťazec, a ďalší, ktorý z toho deserializuje objekt Reťazec:

public class SerializationUtility {public static void main (String [] args) {AppleProduct macBook = new AppleProduct (); macBook.headphonePort = "headphonePort2020"; macBook.thunderboltPort = "thunderboltPort2020"; Reťazec serializedObj = serializeObjectToString (macBook); System.out.println ("Serializovaný objekt AppleProduct na reťazec:"); System.out.println (serializedObj); } public static String serializeObjectToString (Serializable o) {ByteArrayOutputStream baos = nový ByteArrayOutputStream (); ObjectOutputStream oos = nový ObjectOutputStream (baos); oos.writeObject (o); oos.close (); vrátiť Base64.getEncoder (). encodeToString (baos.toByteArray ()); }}
public class DeserializationUtility {public static void main (String [] args) {String serializedObj = ... // ommited for clarity System.out.println ("Deserializing AppleProduct ..."); AppleProduct deserializedObj = (AppleProduct) deSerializeObjectFromString (serializedObj); System.out.println ("Port pre slúchadlá spoločnosti AppleProduct:" + deserializedObj.getHeadphonePort ()); System.out.println ("Port Thunderbolt spoločnosti AppleProduct:" + deserializedObj.getThunderboltPort ()); } public static Object deSerializeObjectFromString (String s) throws IOException, ClassNotFoundException {byte [] data = Base64.getDecoder (). decode (s); ObjectInputStream ois = nový ObjectInputStream (nový ByteArrayInputStream (údaje)); Objekt o = ois.readObject (); ois.close (); návrat o; }}

Začíname behom SerializationUtility.java, ktorý ukladá (serializuje) AppleProduct objekt do a String inštance, kódovanie bajtov pomocou Base64.

Potom pomocou toho String ako argument pre metódu deserializácie bežíme DeserializationUtility.java, ktorý znovu zostavuje (deserializuje) AppleProduct objekt z daného String.

Generovaný výstup by mal byť podobný tomuto:

Serializovány AppleProduct objekt reťazec: rO0ABXNyACljb20uYmFlbGR1bmcuZGVzZXJpYWxpemF0aW9uLkFwcGxlUHJvZHVjdAAAAAAAEta HAgADTAANaGVhZHBob25lUG9ydHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wADmxpZ2h0ZW5pbmdQb3 J0cQB + AAFMAA90aHVuZGVyYm9sdFBvcnRxAH4AAXhwdAARaGVhZHBob25lUG9ydDIwMjBwdAATd Gh1bmRlcmJvbHRQb3J0MjAyMA ==
Deserializácia produktu AppleProduct ... Port pre slúchadlá spoločnosti AppleProdukt: slúchadláPort2020 Thunderbolt port spoločnosti AppleProdukt: thunderboltPort2020

Teraz poďme upraviť serialVersionUIDkonštantný v AppleProduct.java, a znova sa pokúsiť deserializovať the AppleProduct objekt z rovnakého reťazca, ktorý bol vyrobený skôr. Opätovné spustenie DeserializationUtility.java by mal vygenerovať tento výstup.

Deserializácia AppleProduct ... Výnimka vo vlákne „main“ java.io.InvalidClassException: com.baeldung.deserialization.AppleProduct; nekompatibilná lokálna trieda: stream classdesc serialVersionUID = 1234567, lokálna trieda serialVersionUID = 7654321 na java.io.ObjectStreamClass.initNonProxy (ObjectStreamClass.java:616) na java.io.ObjectInputStream.readNonProxyDesc (ObjectInputStream.java.16.30) ObjectInputStream. .java: 373) na adrese com.baeldung.deserialization.DeserializationUtility.deSerializeObjectFromString (DeserializationUtility.java:24) na adrese com.baeldung.deserialization.DeserializationUtility.main (DeserializationUtility.java:15)

Zmenou serialVersionUID triedy sme upravili jej verziu / stav. Vo výsledku sa počas deserializácie nenašli žiadne kompatibilné triedy a InvalidClassException bol vyhodený.

3. Kompatibilné zmeny

Povedzme, že musíme pridať nové pole lightningPort k našim existujúcim AppleProduct trieda:

verejná trieda AppleProduct implementuje Serializable {// ... public String lightningPort; }

Pretože práve pridávame nové pole, žiadna zmena v serialVersionUID bude požadované. To je preto, že, počas procesu deserializácie, nulový bude priradená ako predvolená hodnota pre lightningPort lúka.

Upravme naše DeserializáciaUtility triedy na vytlačenie hodnoty tohto nového poľa:

System.out.println ("port LightningPort spoločnosti AppleProduct:" + deserializedObj.getLightningPort ());

Teraz, keď sme znovu spustili súbor DeserializáciaUtility triedy, uvidíme výstup podobný:

Deserializácia produktu AppleProduct ... Port pre slúchadlá spoločnosti AppleProdukt: slúchadláPort2020 Thunderbolt port spoločnosti AppleProdukt: thunderboltPort2020 Lightning port spoločnosti AppleProdukt: null

4. Predvolená sériová verzia

Ak nedefinujeme a serialVersionUID štát pre a Serializovateľné triedy, potom Java definuje jednu na základe niektorých vlastností samotnej triedy, ako je napríklad názov triedy, polia inštancie atď.

Definujme jednoduchý Serializovateľné trieda:

verejná trieda DefaultSerial implementuje Serializable {}

Ak serializujeme inštanciu tejto triedy, ako je táto:

DefaultSerial inštancia = nový DefaultSerial (); System.out.println (SerializationUtility.serializeObjectToString (inštancia));

Týmto sa vytlačí výpis Base64 serializovaného binárneho súboru:

rO0ABXNyACpjb20uYmFlbGR1bmcuZGVzZXJpYWxpemF0aW9uLkRlZmF1bHRTZXJpYWx9iVz3Lz / mdAIAAHhw

Rovnako ako predtým by sme mali byť schopní deserializovať túto inštanciu zo súhrnu:

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

Niektoré zmeny v tejto triede však môžu narušiť kompatibilitu serializácie. Napríklad, ak pridáme a súkromné pole do tejto triedy:

verejná trieda DefaultSerial implementuje Serializable {private String name; }

A potom sa pokúsme deserializovať rovnaký súhrn Base64 na inštanciu triedy, dostaneme InvalidClassException:

Výnimka vo vlákne „main“ java.io.InvalidClassException: com.baeldung.deserialization.DefaultSerial; nekompatibilná miestna trieda: stream classdesc serialVersionUID = 9045863543269746292, miestna trieda serialVersionUID = -2692722436255640434

Z dôvodu tohto druhu nežiaducej nekompatibility je vždy dobré vyhlásiť a serialVersionUID v Serializovateľné triedy. Takto môžeme zachovať alebo vyvíjať verziu tak, ako sa bude vyvíjať samotná trieda.

5. Záver

V tomto rýchlom článku sme si demonštrovali použitie serialVersionUID konštanta na uľahčenie vytvárania verzií serializovaných údajov.

Ako vždy, ukážky kódu použité v tomto článku nájdete na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found