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 valore serialVersionUID
pari a 0 e lo si annulla con ogni modifica strutturale alla classe che altera 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 la tua funzione readObject () che può leggere vecchi dati. Questo codice personalizzato può quindi controllare serialVersionUID
per sapere in quale versione si trovano i dati e decidere come deserializzare. Questa tecnica di versioning è utile se si memorizzano dati serializzati che sopravvivono a diverse versioni del codice.
Ma la memorizzazione di dati serializzati per così tanto tempo non è molto comune. È molto più comune utilizzare il meccanismo di serializzazione per scrivere temporaneamente dati ad esempio in una cache o inviarli in 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. Al fine di facilitare tale controllo, è necessario mantenere il serialVersionUID
proprio come prima e non dimenticare di aggiornarlo quando si apportano modifiche alle classi.
Se dimentichi di aggiornare il campo, potresti finire con due diverse versioni di una classe con struttura diversa ma con la stessa 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 ti offre la possibilità di non impostare serialVersionUID
manualmente. Invece, un hash della struttura di classe verrà generato in fase di compilazione e utilizzato come id. Questo meccanismo farà in modo che non si abbiano mai strutture di classe diverse con lo stesso ID e quindi non si otterranno questi errori di serializzazione di 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.