La serializzazione è un meccanismo per convertire lo stato di un oggetto in un flusso di byte. La deserializzazione è il processo inverso in cui il flusso di byte viene utilizzato per ricreare l'oggetto Java effettivo in memoria. Questo meccanismo viene utilizzato per rendere persistente l'oggetto.
Il flusso di byte creato è indipendente dalla piattaforma. Pertanto, l'oggetto serializzato su una piattaforma può essere deserializzato su una piattaforma diversa. Per rendere serializzabile un oggetto Java implementiamo il file java.io.Serializable interfaccia. La classe ObjectOutputStream contiene scrivereOggetto() metodo per serializzare un oggetto.
public final void writeObject(Object obj) throws IOException>
La classe ObjectInputStream contiene leggiOggetto() metodo per deserializzare un oggetto.
public final Object readObject() throws IOException, ClassNotFoundException>
Vantaggi della serializzazione
- Per salvare/persistere lo stato di un oggetto.
- Far viaggiare un oggetto attraverso una rete.
È possibile serializzare solo gli oggetti di quelle classi che stanno implementando java.io.Serializable interfaccia. Serializzabile è a interfaccia marcatore (non ha membro dati e metodo). Viene utilizzato per contrassegnare le classi Java in modo che gli oggetti di queste classi possano ottenere determinate funzionalità. Altri esempi di interfacce marcatori sono: - Clonabile e Remoto.
Punti da ricordare
1. Se una classe genitore ha implementato l'interfaccia Serializable, la classe figlia non ha bisogno di implementarla ma viceversa non è vero.
2. Solo i membri dati non statici vengono salvati tramite il processo di serializzazione.
3. I membri dati statici e i membri dati temporanei non vengono salvati tramite il processo di serializzazione. Pertanto, se non desideri salvare il valore di un membro dati non statico, rendilo transitorio.
4. Il costruttore dell'oggetto non viene mai chiamato quando un oggetto viene deserializzato.
5. Gli oggetti associati devono implementare l'interfaccia serializzabile. Esempio :
class A implements Serializable{ // B also implements Serializable // interface. B ob=new B(); }>
SerialVersionUID Il runtime di serializzazione associa un numero di versione a ciascuna classe Serializable denominata 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 siano compatibili rispetto alla serializzazione. Se il destinatario ha caricato una classe per l'oggetto che ha un UID diverso da quello della corrispondente classe del mittente, la deserializzazione risulterà in un InvalidClassException .
Una classe Serializable può dichiarare esplicitamente il proprio UID dichiarando un nome di campo. Deve essere statico, definitivo e di tipo lungo. cioè ANY-ACCESS-MODIFIER statico finale lungo serialVersionUID=42L; Se una classe serializzabile non dichiara esplicitamente un serialVersionUID, il runtime di serializzazione ne calcolerà uno predefinito per quella classe in base a vari aspetti della classe, come descritto in Specifica di serializzazione degli oggetti Java. Tuttavia è fortemente consigliabile che tutte le classi serializzabili dichiarino esplicitamente il valore serialVersionUID, poiché il suo calcolo è altamente sensibile ai dettagli della classe che possono variare a seconda delle implementazioni del compilatore, qualsiasi modifica nella classe o l'utilizzo di ID diversi può influire sui dati serializzati. Si consiglia inoltre di utilizzare il modificatore privato per l'UID poiché non è utile come membro ereditato. serialver Il serialver è uno strumento fornito con JDK. Viene utilizzato per ottenere il numero serialVersionUID per le classi Java.
È possibile eseguire il comando seguente per ottenere serialVersionUID serialver [-classpath classpath] [-show] [classname…] Esempio 1:
Giava
mylive cricket
// Java code for serialization and deserialization> // of a Java object> import> java.io.*;> class> Demo> implements> java.io.Serializable> {> > public> int> a;> > public> String b;> > // Default constructor> > public> Demo(> int> a, String b)> > {> > this> .a = a;> > this> .b = b;> > }> }> class> Test> {> > public> static> void> main(String[] args)> > {> > Demo object => new> Demo(> 1> , 'geeksforgeeks');> > String filename = 'file.ser';> > > // Serialization> > try> > {> > //Saving of object in a file> > FileOutputStream file => new> FileOutputStream(filename);> > ObjectOutputStream out => new> ObjectOutputStream(file);> > > // Method for serialization of object> > out.writeObject(object);> > > out.close();> > file.close();> > > System.out.println('Object has been serialized');> > }> > > catch> (IOException ex)> > {> > System.out.println('IOException is caught');> > }> > Demo object1 => null> ;> > // Deserialization> > try> > {> > // Reading the object from a file> > FileInputStream file => new> FileInputStream(filename);> > ObjectInputStream in => new> ObjectInputStream(file);> > > // Method for deserialization of object> > object1 = (Demo)in.readObject();> > > in.close();> > file.close();> > > System.out.println('Object has been deserialized ');> > System.out.println('a = ' + object1.a);> > System.out.println('b = ' + object1.b);> > }> > > catch> (IOException ex)> > {> > System.out.println('IOException is caught');> > }> > > catch> (ClassNotFoundException ex)> > {> > System.out.println('ClassNotFoundException is caught');> > }> > }> }> |
>
>
Produzione :
Object has been serialized Object has been deserialized a = 1 b = geeksforgeeks>
Esempio 2:
Giava
converti il carattere in una stringa java
// Java code for serialization and deserialization> // of a Java object> import> java.io.*;> class> Emp> implements> Serializable {> private> static> final> long> serialversionUID => > 129348938L;> > transient> int> a;> > static> int> b;> > String name;> > int> age;> > // Default constructor> public> Emp(String name,> int> age,> int> a,> int> b)> > {> > this> .name = name;> > this> .age = age;> > this> .a = a;> > this> .b = b;> > }> }> public> class> SerialExample {> public> static> void> printdata(Emp object1)> > {> > System.out.println('name = ' + object1.name);> > System.out.println('age = ' + object1.age);> > System.out.println('a = ' + object1.a);> > System.out.println('b = ' + object1.b);> > }> public> static> void> main(String[] args)> > {> > Emp object => new> Emp('ab',> 20> ,> 2> ,> 1000> );> > String filename = 'shubham.txt';> > // Serialization> > try> {> > // Saving of object in a file> > FileOutputStream file => new> FileOutputStream> > (filename);> > ObjectOutputStream out => new> ObjectOutputStream> > (file);> > // Method for serialization of object> > out.writeObject(object);> > out.close();> > file.close();> > System.out.println('Object has been serialized
'> > + 'Data before Deserialization.');> > printdata(object);> > // value of static variable changed> > object.b => 2000> ;> > }> > catch> (IOException ex) {> > System.out.println('IOException is caught');> > }> > object => null> ;> > // Deserialization> > try> {> > // Reading the object from a file> > FileInputStream file => new> FileInputStream> > (filename);> > ObjectInputStream in => new> ObjectInputStream> > (file);> > // Method for deserialization of object> > object = (Emp)in.readObject();> > in.close();> > file.close();> > System.out.println('Object has been deserialized
'> > + 'Data after Deserialization.');> > printdata(object);> > // System.out.println('z = ' + object1.z);> > }> > catch> (IOException ex) {> > System.out.println('IOException is caught');> > }> > catch> (ClassNotFoundException ex) {> > System.out.println('ClassNotFoundException' +> > ' is caught');> > }> > }> }> |
>
>
Produzione:
Object has been serialized Data before Deserialization. name = ab age = 20 a = 2 b = 1000 Object has been deserialized Data after Deserialization. name = ab age = 20 a = 0 b = 2000>
Descrizione dell'output: hai visto durante la deserializzazione dell'oggetto che i valori di a e b sono cambiati. Il motivo per cui a era contrassegnato come transitorio e b era statico.
In caso di variabili transitorie:- Una variabile definita con la parola chiave transitoria non viene serializzata durante il processo di serializzazione. Questa variabile verrà inizializzata con il valore predefinito durante la deserializzazione. (es: per gli oggetti è nullo, per gli int è 0).
In caso di Variabili statiche: - Una variabile definita con la parola chiave statica non viene serializzata durante il processo di serializzazione. Questa variabile verrà caricata con il valore corrente definito nella classe durante la deserializzazione.
Transitorio vs finale:
finale le variabili parteciperanno alla serializzazione direttamente tramite i loro valori.
Quindi dichiarare una variabile finale come transitoria non ha alcuna utilità.
//il compilatore assegna il valore alla variabile finale
esempio:
final int x= 10; int y = 20; System.out.println(x);// compiler will replace this as System.out.println(10)->10 perché x è finale. System.out.println(y);//20>
Esempio 3:
Giava
//java code for final with transient> import> java.io.*;> class> Dog> implements> Serializable{> > int> i=> 10> ;> > transient> final> int> j=> 20> ;> }> class> GFG {> > public> static> void> main (String[] args)> throws> IOException,ClassNotFoundException> > {> > Dog d1=> new> Dog();> > //Serialization started> > System.out.println(> 'serialization started'> );> > FileOutputStream fos=> new> FileOutputStream(> 'abc.ser'> );> > ObjectOutputStream oos=> new> ObjectOutputStream(fos);> > oos.writeObject(d1);> > System.out.println(> 'Serialization ended'> );> > > //Deserialization started> > System.out.println(> 'Deserialization started'> );> > FileInputStream fis=> new> FileInputStream(> 'abc.ser'> );> > ObjectInputStream ois=> new> ObjectInputStream(fis);> > Dog d2=(Dog) ois.readObject();> > System.out.println(> 'Deserialization ended'> );> > System.out.println(> 'Dog object data'> );> > //final result> > System.out.println(d2.i+> ' '> +d2.j);> > }> }> |
>
>Produzione
serialization started Serialization ended Deserialization started Deserialization ended Dog object data 10 20>