Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤與異常

Java 多執行緒

Java 同步

Java 網路程式設計

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 其他

Java APIs 與框架

Java 類引用

Java 有用資源

Java - 序列化



Java 提供了一種機制,稱為物件序列化,其中物件可以表示為位元組序列,其中包括物件的資料以及有關物件型別和儲存在物件中資料的型別的資訊。

將序列化的物件寫入檔案後,可以從檔案中讀取並反序列化,即可以使用表示物件及其資料的資料型別資訊和位元組來在記憶體中重新建立物件。

最令人印象深刻的是,整個過程是JVM無關的,這意味著物件可以在一個平臺上序列化,然後在完全不同的平臺上反序列化。

序列化和反序列化物件的方法

ObjectInputStreamObjectOutputStream是包含序列化和反序列化物件方法的高階流。

ObjectOutputStream 類包含許多用於寫入各種資料型別的寫入方法,但其中一種方法尤其突出:

語法

public final void writeObject(Object x) throws IOException

上述方法序列化一個 Object 並將其傳送到輸出流。類似地,ObjectInputStream 類包含以下用於反序列化物件的方法:

語法

public final Object readObject() throws IOException, ClassNotFoundException

此方法從流中檢索下一個 Object 並將其反序列化。返回值為 Object,因此您需要將其強制轉換為其相應的資料型別。

Java 中的序列化是如何工作的?

為了演示 Java 中的序列化是如何工作的,我將使用我們在本書前面討論過的 Employee 類。假設我們有以下 Employee 類,它實現了 Serializable 介面:

演示 Java 中序列化工作的示例

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 介面。

  • 該類中的所有欄位都必須是可序列化的。如果欄位不可序列化,則必須將其標記為transient

如果您想知道某個 Java 標準類是否可序列化,請檢視該類的文件。測試很簡單:如果該類實現了 java.io.Serializable,則它是可序列化的;否則,它不可序列化。

序列化物件

ObjectOutputStream 類用於序列化 Object。以下 SerializeDemo 程式例項化一個 Employee 物件並將其序列化到檔案中。

程式執行完畢後,將建立一個名為 employee.ser 的檔案。程式不會生成任何輸出,但請研究程式碼並嘗試確定程式正在做什麼。

注意 - 將物件序列化到檔案時,Java 中的標準約定是為檔案賦予.ser副檔名。

序列化物件的示例

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

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("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();
      }
   }
}
class Employee implements java.io.Serializable {
   private static final long serialVersionUID = 1L;
   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);
   }
}

輸出

Serialized data is saved in employee.ser

反序列化物件

以下 DeserializeDemo 程式反序列化在前面程式中建立的 Employee 物件。研究該程式並嘗試確定其輸出:

反序列化物件的示例

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

public class DeserializeDemo {

   public static void main(String [] args) {
      Employee e = null;
      try {
         FileInputStream fileIn = new FileInputStream("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);
   }
}
class Employee implements java.io.Serializable {

   private static final long serialVersionUID = 1L;
   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);
   }
}

輸出

Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

Java序列化要點

以下是需要注意的一些要點:

  • try/catch塊 嘗試捕獲由readObject()方法宣告的ClassNotFoundException。為了使JVM能夠反序列化一個物件,它必須能夠找到該類的位元組碼。如果JVM在物件的反序列化過程中找不到某個類,則會丟擲ClassNotFoundException。

  • 請注意,readObject() 的返回值被轉換為Employee引用。

  • 當物件被序列化時,SSN欄位的值為11122333,但由於該欄位是transient的,因此此值未傳送到輸出流。反序列化後的Employee物件的SSN欄位為0。

廣告