Domanda

Eclipse emette avvisi quando manca un serialVersionUID .

  

La classe serializzabile Foo non dichiara un finale statico   campo serialVersionUID di tipo long

Che cos'è serialVersionUID e perché è importante? Mostra un esempio in cui serialVersionUID mancante causerà un problema.

È stato utile?

Soluzione

I documenti per java.io.Serializable è probabilmente una spiegazione altrettanto valida che otterrai:

  

Il runtime di serializzazione associa a ciascuna classe serializzabile un numero di versione, chiamato serialVersionUID , che viene utilizzato durante la deserializzazione per verificare che il mittente e il destinatario di un oggetto serializzato abbiano caricato classi per quell'oggetto che sono compatibile rispetto alla serializzazione. Se il destinatario ha caricato una classe per l'oggetto che ha un serialVersionUID diverso da quello della classe del mittente corrispondente, la deserializzazione comporterà un    InvalidClassException . Una classe serializzabile può dichiarare esplicitamente il proprio serialVersionUID dichiarando un campo denominato serialVersionUID che deve essere statico, finale e di tipo long :

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

Se una classe serializzabile non dichiara esplicitamente un serialVersionUID , il runtime di serializzazione calcolerà un valore predefinito serialVersionUID per quella classe in base a vari aspetti della classe, come descritto nella specifica di serializzazione degli oggetti Java (TM). Tuttavia, è fortemente raccomandato che tutte le classi serializzabili dichiarino esplicitamente i valori serialVersionUID , poiché il calcolo predefinito serialVersionUID è altamente sensibile ai dettagli della classe che possono variare a seconda delle implementazioni del compilatore e può quindi comportare InvalidClassExceptions inattesi durante la deserializzazione. Pertanto, per garantire un valore serialVersionUID coerente tra le diverse implementazioni del compilatore java, una classe serializzabile deve dichiarare un valore serialVersionUID esplicito. Si consiglia inoltre vivamente che dichiarazioni esplicite serialVersionUID utilizzino il modificatore privato ove possibile, poiché tali dichiarazioni si applicano solo ai campi di classe serialVersionUID che dichiarano immediatamente non sono utili come membri ereditati.

Altri suggerimenti

Se stai serializzando solo perché devi serializzare per il bene dell'implementazione (a chi importa se serializzi per un HTTPSession , per esempio ... se è archiviato o meno, probabilmente non non preoccuparti di deserializzare un oggetto modulo), quindi puoi ignorarlo.

Se stai effettivamente utilizzando la serializzazione, è importante solo se prevedi di archiviare e recuperare oggetti utilizzando direttamente la serializzazione. serialVersionUID rappresenta la versione della tua classe e dovresti incrementarla se la versione corrente della tua classe non è retrocompatibile con la sua versione precedente.

Il più delle volte, probabilmente non userete direttamente la serializzazione. In questo caso, genera un SerialVersionUID predefinito facendo clic sull'opzione di correzione rapida e non preoccuparti.

Non posso perdere l'occasione di collegare il libro di Josh Bloch Java efficace (2a edizione). Il capitolo 11 è una risorsa indispensabile per la serializzazione Java.

Per Josh, l'UID generato automaticamente viene generato in base al nome di una classe, alle interfacce implementate e a tutti i membri pubblici e protetti. La modifica di uno di questi in qualsiasi modo cambierà il serialVersionUID . Quindi non è necessario pasticciarli solo se si è certi che non più di una versione della classe sarà mai serializzata (attraverso processi o recuperata dalla memoria in un secondo momento).

Se li ignori per ora e scopri in seguito che devi cambiare la classe in qualche modo ma mantenere la compatibilità con la vecchia versione della classe, puoi usare lo strumento JDK serialver per generare il serialVersionUID sulla vecchia classe e la imposta esplicitamente sulla nuova classe. (A seconda delle modifiche potrebbe essere necessario implementare anche la serializzazione personalizzata aggiungendo i metodi writeObject e readObject - consultare Serializable javadoc o il precedente capitolo 11.)

Puoi dire a Eclipse di ignorare questi avvisi serialVersionUID:

  

Finestra > Preferenze > Java > Compilatore > Errori / Avvertenze > Potenziali problemi di programmazione

Nel caso in cui non lo sapessi, ci sono molti altri avvisi che puoi abilitare in questa sezione (o addirittura avere alcuni segnalati come errori), molti sono molto utili:

  • Potenziali problemi di programmazione: possibile assegnazione booleana accidentale
  • Potenziali problemi di programmazione: accesso puntatore nullo
  • Codice non necessario: la variabile locale non viene mai letta
  • Codice non necessario: controllo null ridondante
  • Codice non necessario: cast non necessario o "instanceof"

e molti altri.

serialVersionUID facilita il controllo delle versioni dei dati serializzati. Il suo valore viene memorizzato con i dati durante la serializzazione. Durante la deserializzazione, viene verificata la stessa versione per vedere come i dati serializzati corrispondono al codice corrente.

Se si desidera eseguire la versione dei dati, si inizia normalmente con un serialVersionUID di 0 e si aggiunge a ogni modifica strutturale alla propria classe che modifica i dati serializzati (aggiungendo o rimuovendo campi non transitori ).

Il meccanismo di deserializzazione incorporato ( in.defaultReadObject () ) rifiuterà di deserializzare dalle vecchie versioni dei dati. Ma se vuoi puoi definire il tuo readObject () - funzione che può leggere vecchi dati. Questo codice personalizzato può quindi controllare serialVersionUID per sapere in quale versione si trovano i dati e decidere come deserializzarli. Questa tecnica di controllo delle versioni è utile se si memorizzano dati serializzati che sopravvivono a diverse versioni del codice.

Ma la memorizzazione di dati serializzati per un arco di tempo così lungo non è molto comune. È molto più comune utilizzare il meccanismo di serializzazione per scrivere temporaneamente i dati in una cache o inviarli sulla rete a un altro programma con la stessa versione delle parti pertinenti della base di codice.

In questo caso non sei interessato a mantenere la compatibilità con le versioni precedenti. Ti preoccupi solo di assicurarti che le basi di codice che comunicano abbiano effettivamente le stesse versioni delle classi pertinenti. Per facilitare tale controllo, è necessario mantenere serialVersionUID proprio come prima e non dimenticare di aggiornarlo quando si apportano modifiche alle proprie classi.

Se dimentichi di aggiornare il campo, potresti finire con due diverse versioni di una classe con struttura diversa ma con lo stesso serialVersionUID . In tal caso, il meccanismo predefinito ( in.defaultReadObject () ) non rileverà alcuna differenza e proverà a deserializzare i dati incompatibili. Ora potresti finire con un errore di runtime criptico o un errore silenzioso (campi null). Questi tipi di errori potrebbero essere difficili da trovare.

Quindi, per aiutare questo caso d'uso, la piattaforma Java offre la possibilità di non impostare manualmente serialVersionUID . Invece, un hash della struttura di classe verrà generato in fase di compilazione e utilizzato come id. Questo meccanismo farà in modo che tu non abbia mai strutture di classe diverse con lo stesso ID e quindi non otterrai questi errori di serializzazione del runtime difficili da rintracciare menzionati sopra.

Ma c'è un lato negativo nella strategia id generata automaticamente. Vale a dire che gli ID generati per la stessa classe potrebbero differire tra compilatori (come menzionato sopra Jon Skeet). Pertanto, se si comunicano dati serializzati tra codice compilato con compilatori diversi, si consiglia comunque di conservare gli ID manualmente.

E se sei retrocompatibile con i tuoi dati come nel primo caso d'uso menzionato, probabilmente vorrai anche mantenere l'ID da solo. Questo al fine di ottenere ID leggibili e avere un maggiore controllo su quando e come cambiano.

  

Che cos'è un serialVersionUID e perché dovrei usarlo?

SerialVersionUID è un identificatore univoco per ogni classe, JVM lo utilizza per confrontare le versioni della classe garantendo che la stessa classe utilizzata durante la serializzazione sia caricata durante la deserializzazione.

Specificarne uno dà più controllo, sebbene JVM ne generi uno se non lo si specifica. Il valore generato può differire tra diversi compilatori. Inoltre, a volte vuoi solo per qualche motivo vietare la deserializzazione di vecchi oggetti serializzati [ incompatibilità con le versioni precedenti ], e in questo caso devi solo cambiare serialVersionUID.

javadocs for Serializable dire :

  

il calcolo predefinito serialVersionUID è altamente sensibile alla classe   dettagli che possono variare a seconda delle implementazioni del compilatore e possono   pertanto si verificano inattivi InvalidClassException durante   deserializzazione.

Pertanto, è necessario dichiarare serialVersionUID perché ci offre un maggiore controllo .

Questo articolo contiene alcuni punti positivi sull'argomento.

La domanda originale ha chiesto 'perché è importante' ed 'esempio' dove questo ID versione seriale sarebbe utile. Bene, ne ho trovato uno.

Supponi di creare una classe Car , di crearne un'istanza e di scriverla in un flusso di oggetti. L'oggetto auto appiattito si trova nel file system per qualche tempo. Nel frattempo, se la classe Car viene modificata aggiungendo un nuovo campo. Successivamente, quando si tenta di leggere (cioè deserializzare) l'oggetto Car appiattito, si ottiene java.io.InvalidClassException - perché a tutte le classi serializzabili viene automaticamente assegnato un identificatore univoco . Questa eccezione viene generata quando l'identificatore della classe non è uguale all'identificatore dell'oggetto appiattito. Se ci pensate davvero, l'eccezione viene generata a causa dell'aggiunta del nuovo campo. Puoi evitare che questa eccezione venga generata controllando tu stesso il controllo delle versioni dichiarando un serialVersionUID esplicito. C'è anche un piccolo vantaggio in termini di prestazioni nel dichiarare esplicitamente il tuo serialVersionUID (perché non deve essere calcolato). Pertanto, è consigliabile aggiungere il proprio serialVersionUID alle classi serializzabili non appena le si crea come mostrato di seguito:

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

Se non dovrete mai serializzare i vostri oggetti su array di byte e inviarli / archiviarli, non dovrete preoccuparvi. Se lo fai, allora devi considerare serialVersionUID poiché il deserializzatore dell'oggetto lo abbinerà alla versione dell'oggetto che ha il suo classloader. Maggiori informazioni al riguardo nelle Specifiche del linguaggio Java.

Se ricevi questo avviso su una classe che non pensi mai alla serializzazione e che non ti sei dichiarato implementa Serializable , è spesso perché hai ereditato da una superclasse, che implementa Serializable. Spesso sarebbe meglio delegare un oggetto del genere invece di usare l'ereditarietà.

Quindi, invece di

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

do

public class MyExample {
    private List<String> myList;

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

e nei metodi pertinenti chiamare myList.foo () anziché this.foo () (o super.foo () ) . (Questo non si adatta in tutti i casi, ma ancora abbastanza spesso.)

Vedo spesso persone che estendono JFrame o simili, quando in realtà hanno solo bisogno di delegare a questo. (Questo aiuta anche per il completamento automatico in un IDE, dal momento che JFrame ha centinaia di metodi, di cui non hai bisogno quando vuoi chiamare quelli personalizzati nella tua classe.)

Un caso in cui l'avviso (o serialVersionUID) è inevitabile è quando si estende da AbstractAction, normalmente in una classe anonima, aggiungendo solo il metodo actionPerformed. Penso che non ci dovrebbe essere un avvertimento in questo caso (dal momento che normalmente non è possibile serializzare in modo affidabile e deserializzare tali classi anonime comunque attraverso diverse versioni della classe), ma non sono sicuro di come il compilatore possa riconoscerlo.

Per comprendere il significato del campo serialVersionUID, è necessario capire come funziona la serializzazione / deserializzazione.

Quando un oggetto di classe serializzabile viene serializzato Java Runtime associa un numero di versione seriale (chiamato serialVersionUID) a questo oggetto serializzato. Nel momento in cui si deserializza questo oggetto serializzato Java Runtime corrisponde al serialVersionUID dell'oggetto serializzato con il serialVersionUID della classe. Se entrambi sono uguali, procede solo con l'ulteriore processo di deserializzazione, altrimenti genera InvalidClassException.

Quindi concludiamo che per rendere efficace il processo di serializzazione / deserializzazione il serialVersionUID dell'oggetto serializzato deve essere equivalente al serialVersionUID della classe. Nel caso in cui il programmatore specifichi esplicitamente il valore serialVersionUID nel programma, lo stesso valore verrà associato all'oggetto serializzato e alla classe, indipendentemente dalla piattaforma di serializzazione e deserializzazione (ad es. La serializzazione potrebbe essere eseguita su piattaforma come Windows usando sun o MS JVM e Deserialization potrebbero trovarsi su piattaforme Linux diverse usando Zing JVM).

Ma nel caso in cui serialVersionUID non sia specificato dal programmatore, durante la serializzazione \ la serializzazione di qualsiasi oggetto, il runtime Java utilizza il proprio algoritmo per calcolarlo. Questo algoritmo di calcolo serialVersionUID varia da un JRE all'altro. È anche possibile che l'ambiente in cui l'oggetto è serializzato stia usando un JRE (es: SUN JVM) e che l'ambiente in cui si verifica la deserializzazione stia usando Linux Jvm (zing). In tali casi serialVersionUID associato all'oggetto serializzato sarà diverso dal serialVersionUID della classe calcolata nell'ambiente di deserializzazione. A sua volta, la deserializzazione non avrà successo. Quindi, per evitare tali situazioni / problemi, il programmatore deve sempre specificare serialVersionUID della classe serializzabile.

Per prima cosa devo spiegare la serializzazione.
Serializzazione consente di convertire l'oggetto in streaming, per l'invio di tale oggetto sulla rete O Salva su file O salva in DB per l'uso della lettera.

Esistono alcune regole per la serializzazione .

  • Un oggetto è serializzabile solo se la sua classe o la sua superclasse implementa l'interfaccia Serializable

  • Un oggetto è serializzabile (esso stesso implementa l'interfaccia Serializable) anche se la sua superclasse non lo è. Tuttavia, la prima superclasse nella gerarchia della classe serializzabile, che non implementa l'interfaccia Serializable, DEVE avere un costruttore no-arg. Se questo viene violato, readObject () produrrà un java.io.InvalidClassException in fase di esecuzione

  • Tutti i tipi primitivi sono serializzabili.

  • I campi transitori (con modificatore transitorio) NON sono serializzati, (cioè non salvati o ripristinati). Una classe che implementa Serializable deve contrassegnare i campi transitori di classi che non supportano la serializzazione (ad esempio, un flusso di file).

  • I campi statici (con modificatore statico) non sono serializzati.

Quando l'oggetto è serializzato JAVA Runtime Associa il numero di versione seriale chiamato serialVersionID.

Dove abbiamo bisogno di serialVersionID: Durante la deserializzazione per verificare che mittente e destinatario siano compatibili rispetto alla serializzazione. Se il destinatario ha caricato la classe con serialVersionID diverso, la deserializzazione terminerà con InvalidClassCastException .
 Una classe serializzabile può dichiarare esplicitamente il proprio serialVersionUID dichiarando un campo denominato "serialVersionUID" che deve essere statico, finale e di tipo lungo :.

Proviamo con un esempio.

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() {
    StringBuffer employee = new StringBuffer();
    employee.append(getEmpName()).append(" is ).append(getEmpAge()).append("
years old  "));
    return employee.toString();
}
}

Crea oggetto serializza

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");
}
}

Deserializ l'oggetto

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());
 }
}    

NOTA: ora modifica serialVersionUID della classe Employee e salva:

private static final long serialVersionUID = 4L;

Ed esegui la classe Reader. Non eseguire la classe Writer e otterrai l'eccezione.

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)

Non preoccuparti, il calcolo predefinito è davvero buono e sufficiente per il 99,9999% dei casi. E se si verificano problemi, è possibile - come già affermato - introdurre l'UID come necessità necessaria (che è altamente improbabile)

Come per un esempio in cui il serialVersionUID mancante potrebbe causare un problema:

Sto lavorando a questa applicazione Java EE composta da un modulo Web che utilizza un modulo EJB . Il modulo Web chiama il modulo EJB in remoto e passa un POJO che implementa Serializable come argomento.

Questa classe POJO è stata impacchettata all'interno del vaso EJB e all'interno del proprio vaso nel WEB-INF / lib del modulo web. Sono in realtà la stessa classe, ma quando impacco il modulo EJB scompatto il jar di questo POJO per impacchettarlo insieme al modulo EJB.

La chiamata al EJB non è riuscita con l'eccezione di seguito perché non avevo dichiarato il suo serialVersionUID :

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

In genere utilizzo serialVersionUID in un contesto: quando so che lascerà il contesto della VM Java.

Lo saprei quando uso ObjectInputStream e ObjectOutputStream per la mia applicazione o se so che una libreria / framework che userò lo userò. SerialVersionID garantisce che diverse VM Java di diverse versioni o fornitori interagiranno correttamente o se viene archiviato e recuperato all'esterno della VM, ad esempio HttpSession , i dati della sessione possono rimanere anche durante il riavvio e l'aggiornamento dell'applicazione server.

Per tutti gli altri casi, utilizzo

@SuppressWarnings("serial")

poiché il più delle volte serialVersionUID predefinito è sufficiente. Ciò include Exception , HttpServlet .

I dati di campo rappresentano alcune informazioni memorizzate nella classe. La classe implementa l'interfaccia Serializable , così eclipse si offrì automaticamente di dichiarare il campo serialVersionUID . Iniziamo con il valore 1 impostato lì.

Se non vuoi che arrivi questo avviso, usa questo:

@SuppressWarnings("serial")

SerialVersionUID viene utilizzato per il controllo della versione dell'oggetto. puoi specificare serialVersionUID anche nel tuo file di classe. La conseguenza di non specificare serialVersionUID è che quando si aggiunge o si modifica un campo in una classe, la classe già serializzata non sarà in grado di recuperare poiché serialVersionUID generato per la nuova classe e per il vecchio oggetto serializzato sarà diverso. Il processo di serializzazione Java si basa sul serialVersionUID corretto per ripristinare lo stato dell'oggetto serializzato e genera java.io.InvalidClassException in caso di mancata corrispondenza serialVersionUID

Ulteriori informazioni: http://javarevisited.blogspot.com/ 2011/04 / top-10-java-serializzazione-interview.html # ixzz3VQxnpOPZ

Sarebbe bello se CheckStyle potesse verificare che serialVersionUID su una classe che implementa Serializable abbia un buon valore, cioè che corrisponda a ciò che il generatore ID versione seriale produrrebbe. Se hai un progetto con molti DTO serializzabili, ad esempio, ricordare di eliminare il serialVersionUID esistente e rigenerarlo è una seccatura, e attualmente l'unico modo (che conosco) di verificare questo è rigenerare per ogni classe e confrontarlo con quello vecchio. Questo è molto doloroso.

Perché usare SerialVersionUID all'interno della classe Serializable in Java?

Durante la serializzazione , il runtime Java crea un numero di versione per una classe, in modo da poterlo serializzare in un secondo momento. Questo numero di versione è noto come SerialVersionUID in Java.

SerialVersionUID viene utilizzato per la versione dei dati serializzati. Puoi deserializzare una classe solo se SerialVersionUID corrisponde all'istanza serializzata. Quando non dichiariamo SerialVersionUID nella nostra classe, il runtime Java lo genera per noi ma non è raccomandato. Si consiglia di dichiarare SerialVersionUID come private static final long per evitare il meccanismo predefinito.

Quando si dichiara una classe come serializzabile implementando l'interfaccia marker java.io.Serializable , il runtime Java persiste l'istanza di quella classe sul disco utilizzando il meccanismo di serializzazione predefinito, fornito non hai personalizzato il processo utilizzando l'interfaccia Externalizable .

vedi anche Perché usare SerialVersionUID all'interno della classe Serializable in Java

Codice: javassist.SerialVersionUID

Se vuoi modificare un numero enorme di classi che non hanno impostato serialVersionUID in primo luogo mantenendo la compatibilità con le vecchie classi, strumenti come IntelliJ Idea, Eclipse non riescono poiché generano numeri casuali e non funzionano su un mucchio di file in una volta sola. Mi viene in mente il seguente script bash (mi dispiace per gli utenti Windows, considera l'acquisto di un Mac o la conversione in Linux) per apportare facilmente modifiche al problema serialVersionUID:

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 

Se vuoi modificare un numero enorme di classi che non hanno impostato serialVersionUID in primo luogo mantenendo la compatibilità con le vecchie classi, strumenti come IntelliJ Idea, Eclipse non riescono poiché generano numeri casuali e non funzionano su un mucchio di file in una volta sola. Mi viene in mente il seguente script bash (mi dispiace per gli utenti Windows, considera l'acquisto di un Mac o la conversione in Linux) per apportare facilmente modifiche al problema serialVersionUID:

add_serialVersionUID.sh < myJavaToAmend.lst

salvi questo script, dì add_serialVersionUID.sh a te ~ / bin. Quindi lo esegui nella directory principale del tuo progetto Maven o Gradle come:

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

Questo .lst include l'elenco dei file java per aggiungere serialVersionUID nel seguente formato:

<*>

Questo script utilizza lo strumento JVK serialVer sotto il cofano. Quindi assicurati che $ JAVA_HOME / bin sia nel PERCORSO.

; printf qq{%s\n}, q{ private $seruidstr} if /public class/" $src_dir/$f done

salvi questo script, dì add_serialVersionUID.sh a te ~ / bin. Quindi lo esegui nella directory principale del tuo progetto Maven o Gradle come:

<*>

Questo .lst include l'elenco dei file java per aggiungere serialVersionUID nel seguente formato:

<*>

Questo script utilizza lo strumento JVK serialVer sotto il cofano. Quindi assicurati che $ JAVA_HOME / bin sia nel PERCORSO.

Questa domanda è ben documentata in Effective Java da Joshua Bloch. Un ottimo libro e assolutamente da leggere. Descriverò alcuni dei motivi seguenti:

Il runtime di serializzazione presenta un numero chiamato Versione seriale per ogni classe serializzabile. Questo numero si chiama serialVersionUID. Ora c'è un po 'di matematica dietro questo numero e viene fuori in base ai campi / metodi definiti nella classe. Per la stessa classe viene sempre generata la stessa versione. Questo numero viene utilizzato durante la deserializzazione per verificare che il mittente e il destinatario di un oggetto serializzato abbiano caricato classi per quell'oggetto compatibili rispetto alla serializzazione. Se il destinatario ha caricato una classe per l'oggetto che ha un serialVersionUID diverso da quello della classe del mittente corrispondente, la deserializzazione si tradurrà in una InvalidClassException.

Se la classe è serializzabile, puoi anche dichiarare esplicitamente il tuo serialVersionUID dichiarando un campo chiamato "serialVersionUID" deve essere statico, finale e di tipo lungo. La maggior parte degli IDE come Eclipse ti aiutano a generare quella stringa lunga.

Ogni volta che un oggetto viene serializzato, l'oggetto viene timbrato con un numero ID versione per la classe dell'oggetto. Questo ID viene chiamato serialVersionUID ed è calcolato in base alle informazioni sulla struttura della classe. Supponiamo di aver creato una classe Employee e abbia l'ID versione # 333 (assegnato da JVM), Ora quando serializzerai l'oggetto di quella classe (Suppose object Employee), JVM assegnerà l'UID come # 333.

Prendi in considerazione una situazione: in futuro dovrai modificare o cambiare la tua classe e in quel caso quando la modifichi, JVM le assegnerà un nuovo UID (Supponiamo # 444). Ora, quando si tenta di deserializzare l'oggetto dipendente, JVM confronterà l'ID versione (oggetto dipendente) serializzato (n. 333) con quello della classe cioè n. 444 (da quando è stato modificato). A confronto JVM troverà entrambe le versioni UID diverse e quindi la deserializzazione fallirà. Quindi se serialVersionID per ogni classe è definito dal programmatore stesso. Sarà lo stesso anche se la classe si evolverà in futuro e quindi JVM troverà sempre che la classe è compatibile con l'oggetto serializzato anche se la classe viene modificata. Per maggiori informazioni puoi consultare il capitolo 14 di HEAD FIRST JAVA.

Una semplice spiegazione:

  1. Stai serializzando i dati?

    La serializzazione fondamentalmente sta scrivendo i dati della classe su un file / stream / etc. La deserializzazione sta leggendo i dati in una classe.

  2. Intendi andare in produzione?

    Se stai testando qualcosa con dati non importanti / falsi, non preoccuparti (a meno che tu non stia testando direttamente la serializzazione).

  3. È questa la prima versione?

    In tal caso, impostare serialVersionUID = 1L .

  4. Questa è la seconda, terza, ecc. versione prod?

    Ora devi preoccuparti di serialVersionUID e dovresti approfondire.

Fondamentalmente, se non aggiorni la versione correttamente quando aggiorni una classe che devi scrivere / leggere, otterrai un errore quando provi a leggere i vecchi dati.

Per farla breve, questo campo viene utilizzato per verificare se i dati serializzati possono essere deserializzati correttamente. La serializzazione e la deserializzazione vengono spesso eseguite da diverse copie del programma, ad esempio il server converte l'oggetto in stringa e il client converte la stringa ricevuta in oggetto. Questo campo indica che entrambi operano con la stessa idea di cosa sia questo oggetto. Questo campo aiuta quando:

  • hai molte copie diverse del tuo programma in luoghi diversi (come 1 server e 100 client). Se cambierai il tuo oggetto, modificherai il tuo numero di versione e dimenticherai di aggiornare uno di questi client, saprà che non è in grado di deserializzare

  • hai archiviato i tuoi dati in alcuni file e in seguito provi ad aprirli con la versione aggiornata del tuo programma con oggetto modificato - saprai che questo file non è compatibile se mantieni la tua versione corretta

Quando è importante?

Più ovvio: se aggiungi alcuni campi al tuo oggetto, le versioni precedenti non saranno in grado di usarli perché non hanno questi campi nella struttura degli oggetti.

Meno ovvio: quando si deserializza l'oggetto, i campi che non erano presenti nella stringa verranno mantenuti come NULL. Se hai rimosso il campo dal tuo oggetto, le versioni precedenti manterranno questo campo come sempre-NULL che può portare a comportamenti errati se le versioni precedenti si basano sui dati in questo campo (comunque lo hai creato per qualcosa, non solo per divertimento :-))

Almeno ovvio: a volte cambi l'idea che hai inserito nel significato di alcuni campi. Ad esempio, quando hai 12 anni intendi "bicicletta". sotto "bici", ma a 18 anni intendi "moto" - se i tuoi amici ti inviteranno a " giro in bicicletta attraverso la città " e sarai l'unico che è venuto in bicicletta, capirai quanto sia importante mantenere lo stesso significato attraverso i campi :-)

In primo luogo per rispondere alla tua domanda, quando non dichiariamo SerialVersionUID nella nostra classe, il runtime Java lo genera per noi, ma quel processo è sensibile a molti metadati di classe tra cui numero di campi, tipo di campi, modificatore di accesso dei campi , interfaccia implementata per classe ecc. Pertanto si consiglia di dichiararlo noi stessi ed Eclipse ti avverte dello stesso.

serializzazione: Lavoriamo spesso con oggetti importanti il ??cui stato (dati nelle variabili dell'oggetto) è così importante che non possiamo rischiare di perderli a causa di interruzioni dell'alimentazione / del sistema (o) guasti della rete in caso di invio dello stato dell'oggetto ad altre macchine. La soluzione per questo problema è denominata " Persistenza " che significa semplicemente persistere (conservare / salvare) i dati. La serializzazione è uno dei molti altri modi per raggiungere la persistenza (salvando i dati su disco / memoria). Quando si salva lo stato dell'oggetto, è importante creare un'identità per l'oggetto, per poterlo rileggere correttamente (deserializzazione). Questa identificazione univoca è ID è SerialVersionUID.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top