Serializable接口的背後

序列化是什麼?

  序列化就是將一個對象的狀態(各個屬性量)保存起來,而後在適當的時候再得到。序列化分爲兩大部分:序列化和反序列化。java

  • 序列化是這個過程的第一部分,將數據分解成字節流,以便存儲在文件中或在網絡上傳輸。
  • 反序列化就是打開字節流並重構對象。對象序列化不只要將基本數據類型轉換成字節表示,有時還要恢復數據。恢復數據要求有恢復數據的對象實例

何時使用序列化: 

  • 對象序列化能夠實現分佈式對象。主要應用例如:RMI要利用對象序列化運行遠程主機上的服務,就像在本地機上運行對象時同樣。
  • java對象序列化不只保留一個對象的數據,並且遞歸保存對象引用的每一個對象的數據。能夠將整個對象層次寫入字節流中,能夠保存在文件中或在網絡鏈接上傳遞。利用對象序列化能夠進行對象的"深複製",即複製對象自己及引用的對象自己。序列化一個對象可能獲得整個對象序列。

序列化的特色:

  • 若是某個類可以被序列化,其子類也能夠被序列化。若是該類有父類,則分兩種狀況來考慮,若是該父類已經實現了可序列化接口。則其父類的相應字段及屬性的處理和該類相同;若是該類的父類沒有實現可序列化接口,則該類的父類全部的字段屬性將不會序列化。 (2)聲明爲static和transient類型的成員數據不能被序列化。由於static表明類的狀態, transient表明對象的臨時數據;
  • 相關的類和接口:在java.io包中提供的涉及對象的序列化的類與接口有ObjectOutput接口、ObjectOutputStream類、ObjectInput接口、ObjectInputStream類。
    • ObjectOutput接口:它繼承DataOutput接口而且支持對象的序列化,其內的writeObject()方法實現存儲一個對象。ObjectInput接口:它繼承DataInput接口而且支持對象的序列化,其內的readObject()方法實現讀取一個對象。
    • ObjectOutputStream類:它繼承OutputStream類而且實現ObjectOutput接口。利用該類來實現將對象存儲(調用ObjectOutput接口中的writeObject()方法)。ObjectInputStream類:它繼承InputStream類而且實現ObjectInput接口。利用該類來實現讀取一個對象(調用ObjectInput接口中的readObject()方法)。


  對於父類的處理,若是父類沒有實現序列化接口,則其必須有默認的構造函數(即沒有參數的構造函數)。不然編譯的時候就會報錯。在反序列化的時候,默認構造函數會被調用。可是若把父類標記爲能夠序列化,則在反序列化的時候,其默認構造函數不會被調用。這是爲何呢?這是由於Java 對序列化的對象進行反序列化的時候,直接從流裏獲取其對象數據來生成一個對象實例,而不是經過其構造函數來完成。安全

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * Author: Leo Sun
 * Blog: http://kaffa.im/
 * Date: Aug 12, 2014
 */
public class SerializableDemo {

    public static void main(String[] args) {
        Cat cat = new Cat();
        try {
            FileOutputStream fos = new FileOutputStream("catDemo.out");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            System.out.println(" 1> " + cat.getName());
            cat.setName("My Cat");
            oos.writeObject(cat);
            oos.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        try {
            FileInputStream fis = new FileInputStream("catDemo.out");
            ObjectInputStream ois = new ObjectInputStream(fis);
            cat = (Cat) ois.readObject();
            System.out.println(" 2> " + cat.getName());
            ois.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

class Cat implements Serializable {
    
    private static final long serialVersionUID = -5426949996723910122L;
    private String name;

    public Cat() {
        this.name = "new cat";
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

注:writeObject和readObject自己就是線程安全的,傳輸過程當中是不容許被併發訪問的。因此對象能一個一個接連不斷的傳過來網絡

相關文章
相關標籤/搜索