序列化 (Serialization)是將物件的狀態資訊轉換為可儲存或傳送的形式的過程。一般將一個物件儲存至一個儲存媒介,例如檔案或是記億體緩衝等。在網路傳輸過程中,可以是位元組或XML等格式。而位元組的或XML編碼格式可以還原完全相等的物件。這個相反的過程又稱為反序列化。
Java物件的序列化與反序列化
在Java中,我們可以透過多種方式來建立對象,並且只要物件沒有被回收我們都可以重複使用該物件。但是,我們創建出來的這些Java物件都是存在於JVM的堆記憶體中的。只有JVM處於運作狀態的時候,這些物件才可能存在。一旦JVM停止運行,這些物件的狀態也就隨之而失去了。
但是在真實的應用場景中,我們需要將這些物件持久化下來,並且能夠在需要的時候把物件重新讀取出來。 Java的物件序列化可以幫助我們實現該功能。
物件序列化機制(object serialization)是Java語言內建的一種物件持久化方式,透過物件序列化,可以把物件的狀態保存為位元組數組,並且可以在有需要的時候將這個位元組數組透過反序列化的方式再轉換成物件。物件序列化可以很容易的在JVM中的活動物件和位元組數組(流)之間進行轉換。
在Java中,物件的序列化與反序列化被廣泛地應用到RMI(遠端方法呼叫)及網路傳輸。
相關介面及類別
Java為了方便開發人員將Java物件進行序列化及反序列化提供了一套方便的API來支援。其中包括以下介面和類別:
java.io.Serializable
java.io.Externalizable
『Out java.io.ExternalizableObject🎀〜!3!樣
ObjectInputStream Serializable 介面類別透過實作java.io.Serializable 介面以啟用其序列化功能。未實作此介面的類別將無法使其任何狀態序列化或反序列化。可序列化類別的所有子類型本身都是可序列化的。序列化介面沒有方法或字段,僅用於標識可序列化的語義。 (該介面並沒有方法和字段,為什麼只有實現了該介面的類別的物件才能被序列化呢?)
當試圖對一個物件進行序列化的時候,如果遇到不支援 Serializable 介面的物件。在此情況下,將拋出NotSerializableException。 如果要序列化的類別有父類,要想同時將在父類中定義過的變數持久化下來,那麼父類別也應該整合java.io.Serializable介面。
以下是一個實作了java.io.Serializable介面的類別
package com.hollischaung.serialization.SerializableDemos; import java.io.Serializable; /** * Created by hollis on 16/2/17. * 实现Serializable接口 */ public class User1 implements Serializable { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
透過下面的程式碼進行序列化及反序列化
package com.hollischaung.serialization.SerializableDemos; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import java.io.*; /** * Created by hollis on 16/2/17. * SerializableDemo1 结合SerializableDemo2说明 一个类要想被序列化必须实现Serializable接口 */ public class SerializableDemo1 { public static void main(String[] args) { //Initializes The Object User1 user = new User1(); user.setName("hollis"); user.setAge(23); System.out.println(user); //Write Obj to File ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(new FileOutputStream("tempFile")); oos.writeObject(user); } catch (IOException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(oos); } //Read Obj from File File file = new File("tempFile"); ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream(file)); User1 newUser = (User1) ois.readObject(); System.out.println(newUser); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(ois); try { FileUtils.forceDelete(file); } catch (IOException e) { e.printStackTrace(); } } } } //OutPut: //User{name='hollis', age=23} //User{name='hollis', age=23}