English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Java fornisce un meccanismo di serializzazione degli oggetti, in cui un oggetto può essere rappresentato come una sequenza di byte, che include i dati dell'oggetto, le informazioni sul tipo dell'oggetto e i tipi di dati memorizzati nell'oggetto.
Dopo aver scritto l'oggetto serializzato su un file, è possibile leggerlo dal file e deserializzarlo, il che significa che le informazioni sul tipo dell'oggetto, i dati dell'oggetto e i tipi di dati memorizzati nell'oggetto possono essere utilizzati per creare un nuovo oggetto in memoria.
L'intero processo è indipendente dal Java Virtual Machine (JVM), il che significa che un oggetto serializzato su una piattaforma può essere deserializzato su un'altra piattaforma completamente diversa.
Le classi ObjectInputStream e ObjectOutputStream sono flussi a livello di alta complessità, che contengono metodi per deserializzare e serializzare oggetti.
La classe ObjectOutputStream contiene molti metodi per scrivere vari tipi di dati, ma c'è un metodo eccezionale:
public final void writeObject(Object x) throws IOException
Il metodo sopra serializza un oggetto e lo invia al flusso di output. La classe ObjectInputStream simile contiene il seguente metodo per deserializzare un oggetto:
public final Object readObject() throws IOException ClassNotFoundException
Questa metodo estrae l'oggetto successivo dal flusso e lo deserializza. Il suo valore di ritorno è Object, quindi devi convertirlo nel tipo di dati appropriato.
Per dimostrare come funziona la serializzazione in Java, utilizzerò la classe Employee menzionata nel precedente tutorial, supponendo che abbiamo definito la seguente classe Employee, che implementa l'interfaccia Serializable.
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); } }
请注意,一个类的对象要想序列化成功,必须满足两个条件:
该类必须实现 java.io.Serializable 接口。
该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。
如果你想知道一个 Java 标准类是否是可序列化的,请查看该类的文档。检验一个类的示例是否能序列化十分简单,只需要查看该类有没有实现 java.io.Serializable 接口。
ObjectOutputStream 类用来序列化一个对象,如下的 SerializeDemo 实例示例化了一个 Employee 对象,并将该对象序列化到一个文件中。
该程序执行后,就创建了一个名为 employee.ser 的文件。该程序没有任何输出,但是你可以通过代码研读来理解程序的作用。
注意: 当序列化一个对象到文件时,按照 Java 的标准约定是给文件一个 .ser 扩展名。
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("I dati serializzati sono salvati in /tmp/employee.ser"); catch(IOException i) { i.printStackTrace(); } } }
Il seguente programma DeserializeDemo è un esempio di deserializzazione, /tmp/employee.ser contiene l'oggetto Employee.
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("Classe Employee non trovata"); c.printStackTrace(); return; } System.out.println("Deserializzazione Employee..."); System.out.println("Nome: " + e.name); System.out.println("Indirizzo: " + e.address); System.out.println("SSN: " + e.SSN); System.out.println("Numero: " + e.number); } }
Il risultato della compilazione e dell'esecuzione del programma è come segue:
Employee deserializzato... Nome: Reyan Ali Indirizzo: Phokka Kuan, Ambehta Peer SSN: 0 Numero:101
Ecco alcuni punti da notare:
Il blocco try/catch nel metodo readObject() tenta di catturare l'eccezione ClassNotFoundException. Perché un oggetto JVM possa essere deserializzato, il tipo deve essere in grado di trovare i byte code. Se il JVM non riesce a trovare il tipo durante il processo di deserializzazione dell'oggetto, viene lanciata un'eccezione ClassNotFoundException.
Attenzione, il valore di ritorno del metodo readObject() viene trasformato in un riferimento Employee.
Quando l'oggetto viene serializzato, il valore dell'attributo SSN è 111222333, ma poiché l'attributo è temporaneo, questo valore non è stato inviato al flusso di output. Pertanto, dopo la deserializzazione, l'attributo SSN dell'oggetto Employee è 0.