Java 中的基本序列化

什麼是序列化

序列化是將物件的狀態(包括其引用)轉換為位元組序列的過程,以及在將來某個時間將這些位元組重建為活動物件的過程。如果要保留物件,則使用序列化。Java RMI 也使用它來在 JVM 之間傳遞物件,作為從客戶端到伺服器的方法呼叫中的引數,或者作為方法呼叫的返回值,或者作為遠端方法丟擲的異常。通常,當我們希望物件在 JVM 的生命週期之外存在時,使用序列化。

java.io.Serializable 是一個標記介面(沒有主體)。它僅用於將 Java 類標記為可序列化。

與每個序列化類版本號,稱為 serialVersionUID,該過程中使用的序列化執行時相關聯 -serialization 以驗證序列化物件的傳送者和接收者都載入的類該物件是相對於序列相容。如果接收者已經為物件提供了一個類,該物件的 serialVersionUID 與對應的傳送者類的 serialVersionUID 不同,那麼反序列化將導致 InvalidClassException。可序列化的類可以通過宣告名為 serialVersionUID 的欄位來明確宣告自己的 serialVersionUID,該欄位必須是 static, final, 且型別為 long

ANY-ACCESS-MODIFIER static final long serialVersionUID = 1L;

如何使類符合序列化條件

要保持物件,相應的類必須實現 java.io.Serializable 介面。

import java.io.Serializable;

public class SerialClass implements Serializable {

    private static final long serialVersionUID = 1L;  
    private Date currentTime;
    
    public SerialClass() {
        currentTime = Calendar.getInstance().getTime();
    }

    public Date getCurrentTime() {
        return currentTime;
    }
}

如何將物件寫入檔案

現在我們需要將此物件寫入檔案系統。為此,我們使用 java.io.ObjectOutputStream

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;

public class PersistSerialClass {

    public static void main(String [] args) {
        String filename = "time.ser";            
        SerialClass time = new SerialClass(); //We will write this object to file system.
        try {
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename));
            out.writeObject(time); //Write byte stream to file system.
            out.close();
        } catch(IOException ex){
            ex.printStackTrace();
        }
     }
 }

如何從序列化狀態重新建立物件

使用 java.io.ObjectInputStream 可以在以後從檔案系統讀取儲存的物件,如下所示:

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.java.lang.ClassNotFoundException;

 public class ReadSerialClass {

    public static void main(String [] args) {
        String filename = "time.ser";    
        SerialClass time = null;

        try {
            ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename));
            time = (SerialClass)in.readObject();
            in.close();
        } catch(IOException ex){
            ex.printStackTrace();
        } catch(ClassNotFoundException cnfe){
            cnfe.printStackTrace();
        }
        // print out restored time
        System.out.println("Restored time: " + time.getTime());
     }
 }

序列化類是二進位制形式。如果類定義發生更改,則反序列化可能會出現問題: 有關詳細資訊,請參閱 Java 序列化規範的“序列化物件版本控制”一章

序列化物件序列化它作為根的整個物件圖,並在存在迴圈圖的情況下正確執行。提供了一種 reset() 方法來強制 ObjectOutputStream 忘記已經序列化的物件。

瞬態場 - 序列化