“你會記得今天我們研究了將對象保存到文件中並從文件中讀取它們嗎?”

“是的,我們剛剛保存到輸出流,從輸入流讀取。”

“幹得好,阿米戈。很高興聽到你注意到這些細節。你能完成代碼以便它保存到文件並從文件中讀取嗎?”

“完成什麼?!聲明一個 FileInputStream 和 FileOutputStream 並將它們傳遞給保存和加載方法。這裡沒有什麼可混淆的。超級簡單。”

“我為你感到高興。現在來一個新話題:連載。”

序列化與我們剛才所做的幾乎相同,但更酷並且直接內置到 Java 機器中。Java 機器可以存儲和加載它的對象。它甚至不需要 save 和 load 方法來完成:所有對像都存儲在 Java 機器中,並且它可以完全訪問它們。”

我們只是獲取對象並將其保存到流中並從流中讀取:

代碼
public static void main(String[] args) throws Exception
{
 Cat cat = new Cat();

 //Save a cat to file
 FileOutputStream fileOutput = new FileOutputStream("cat.dat");
 ObjectOutputStream outputStream = new ObjectOutputStream(fileOutput);
 outputStream.writeObject(cat);
 fileOutput.close();
 outputStream.close();

 //Load a cat from file
 FileInputStream fiStream = new FileInputStream("cat.dat");
 ObjectInputStream objectStream = new ObjectInputStream(fiStream);
 Object object = objectStream.readObject();
 fiStream.close();
 objectStream.close();

 Cat newCat = (Cat)object;
}

“就是這樣?”

“完全正確。有一個非常龐大和復雜的序列化機制,可以讓我們保存到流中並從幾乎任何數據類型的流中讀取。”

“幾乎所有。所以不是任何數據類型?”

“是的,事實是並不是所有的對像都具有被保存的固有能力。有些對象並沒有在內部存儲所有數據。相反,它們只是引用其他對象和/或數據源。例如,控制台(System. in),一個輸入流(InputStream),以及其他東西。”

這就是 Java 的創建者想出特殊的Serializable接口標記的原因。它被稱為marker,因為它不包含任何數據和方法。它僅用於“標記”或“標記”類。如果我們相信我們的類在內部存儲它的所有數據,那麼我們可以用implements Serializable標記它。

這是一個支持序列化的 «cat» 示例:

代碼
class Cat implements Serializable
{
 public String name;
 public int age;
 public int weight;
}

當我們嘗試序列化(保存)一個對象時,Java 機器會檢查它是否支持序列化:它是否實現了 Serializable 接口?如果是,則保存該對象。如果不是,那麼它會拋出一個異常來表明序列化是不可能的。
這裡需要明白一個可序列化對象必須只由可序列化對象組成。

“嗯,這很有道理。你不能不保存部分就保存整體。”

“確切地。”

“那麼整數、字符串和數組列表呢?”

“他們都支持序列化。Java 的創建者特別注意確保這發生了。這裡應該沒有任何問題。”

此外,對象的類型在對像被序列化時被保存。現在您可以在對像變量中保存對 Cat 對象的引用。一切都會很好地序列化和反序列化。

“反序列化?”

反序列化是反轉序列化的過程:從流/文件中讀取和重建對象。”

“啊,那不用問了。”