Java - Serializzazione
Java fornisce un meccanismo, chiamato serializzazione degli oggetti, in cui un oggetto può essere rappresentato come una sequenza di byte che include i dati dell'oggetto, nonché le informazioni sul tipo di oggetto e sui tipi di dati memorizzati nell'oggetto.
Dopo che un oggetto serializzato è stato scritto in un file, può essere letto dal file e deserializzato, ovvero le informazioni sul tipo ei byte che rappresentano l'oggetto ei suoi dati possono essere utilizzati per ricreare l'oggetto in memoria.
La cosa più impressionante è che l'intero processo è indipendente dalla JVM, il che significa che un oggetto può essere serializzato su una piattaforma e deserializzato su una piattaforma completamente diversa.
Classi ObjectInputStream e ObjectOutputStream sono flussi di alto livello che contengono i metodi per serializzare e deserializzare un oggetto.
La classe ObjectOutputStream contiene molti metodi di scrittura per scrivere vari tipi di dati, ma un metodo in particolare si distingue:
public final void writeObject(Object x) throws IOException
Il metodo precedente serializza un oggetto e lo invia al flusso di output. Allo stesso modo, la classe ObjectInputStream contiene il seguente metodo per deserializzare un oggetto:
public final Object readObject() throws IOException, ClassNotFoundException
Questo metodo recupera l'oggetto successivo dal flusso e lo deserializza. Il valore restituito è Object, quindi sarà necessario eseguirne il cast al tipo di dati appropriato.
Per dimostrare come funziona la serializzazione in Java, userò la classe Employee di cui abbiamo discusso all'inizio del libro. Supponiamo di avere la seguente classe Employee, che implementa l'interfaccia Serializable:
Esempio
public class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int SSN;
public int number;
public void mailCheck() {
System.out.println("Mailing a check to " + name + " " + address);
}
}
Si noti che affinché una classe venga serializzata correttamente, devono essere soddisfatte due condizioni:
La classe deve implementare l'interfaccia java.io.Serializable.
Tutti i campi della classe devono essere serializzabili. Se un campo non è serializzabile, deve essere contrassegnatotransient.
Se sei curioso di sapere se una Java Standard Class è serializzabile o meno, controlla la documentazione per la classe. Il test è semplice: se la classe implementa java.io.Serializable, allora è serializzabile; altrimenti non lo è.
Serializzazione di un oggetto
La classe ObjectOutputStream viene utilizzata per serializzare un oggetto. Il seguente programma SerializeDemo crea un'istanza di un oggetto Employee e lo serializza in un file.
Al termine dell'esecuzione del programma, viene creato un file denominato employee.ser. Il programma non genera alcun output, ma studia il codice e cerca di determinare cosa sta facendo il programma.
Note - Quando si serializza un oggetto in un file, la convenzione standard in Java è di dare al file un .ser estensione.
Esempio
import java.io.*;
public class SerializeDemo {
public static void main(String [] args) {
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try {
FileOutputStream fileOut =
new FileOutputStream("/tmp/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
} catch (IOException i) {
i.printStackTrace();
}
}
}
Deserializzazione di un oggetto
Il seguente programma DeserializeDemo deserializza l'oggetto Employee creato nel programma SerializeDemo. Studia il programma e prova a determinarne l'output -
Esempio
import java.io.*;
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
Questo produrrà il seguente risultato:
Produzione
Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101
Di seguito sono riportati i punti importanti da notare:
Il blocco try / catch tenta di catturare un'eccezione ClassNotFoundException, dichiarata dal metodo readObject (). Affinché una JVM sia in grado di deserializzare un oggetto, deve essere in grado di trovare il bytecode per la classe. Se la JVM non riesce a trovare una classe durante la deserializzazione di un oggetto, genera un'eccezione ClassNotFoundException.
Si noti che viene eseguito il cast del valore restituito di readObject () a un riferimento Employee.
Il valore del campo SSN era 11122333 quando l'oggetto è stato serializzato, ma poiché il campo è transitorio, questo valore non è stato inviato al flusso di output. Il campo SSN dell'oggetto deserializzato Employee è 0.