Java序列化反序列化、Serializable、Parcelable 知識總結

前言

本博客對Java序列化反序列化、Serializable、Parcelable 知識的一個總結。在開發中我們發現Android中Intent傳遞對象有兩種方法:一是Bundle.putSerializable(Key,Object),另一種是Bundle.putParcelable(Key,Object)。當然這些Object是有一定的條件的,前者是實現了Serializable接口,而後者是實現了Parcelable接口。

一、java序列化、反序列化

推薦博文:java序列化、反序列化

1、定義:

Java序列化是指把Java對象轉換爲字節流的過程;而Java反序列化是指把字節流恢復爲Java對象的過程。

2.爲什麼需要序列化與反序列化?

1)永久性保存對象,保存對象的字節序列到本地文件中;

2)通過序列化對象在網絡中傳遞對象;

3)通過序列化在進程間傳遞對象。

3、如何實現Java序列化與反序列化

  • JDK類庫中序列化API

    • java.io.ObjectOutputStream:對象輸出流
      它的writeObject(Object obj)方法可以對object對象進行序列化,把得到的字節流寫到一個目標輸出流中。
    • java.io.ObjectInputStream:對象輸入流,它的readObject()方法在輸入流中讀取字節流,再把它們反序列化成爲一個對象。
  • 序列化、反序列化代碼示例

    • 創建user對象:
    public class User  {
    // transient、static 修飾的成員變量將不會被序列化
    private transient String tag = null;
    public String name;
    public int id;

    public User(String name, int id) {
        this.name = name;
        this.id = id;
        }
    }
  • 對象序列化:
 file = new File("D:\\student.txt");
 User user = new User("張三", 22); 
 FileOutputStream fos = new  FileOutputStream(file);
 ObjectOutputStream oos = new ObjectOutputStream(fos);
 oos.writeObject(user);
 oos.flush();
 oos.close();
 fos.close();
  • 對象反序列化:
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
User user = (User) ois.readObject();
ois.close();

二、 Serializable

1、定義

Serializable 是Java用於標識可序列化定義的一個抽象空接口,對象實現了Serializable接口,標識該類可以被序列化、反序列化。Java 虛擬機會自動對該對象序列化、反系列化。

2、優勢與劣勢

1) 使用簡單,很方便將對象存儲到設備、網絡傳輸。
2)開銷很大,序列化、反序列化過程需要使用外部存儲器,有大量的I/O操作。

三、 Parcelable

推薦博文:探索Android中的Parcel機制

1、定義

Parcelable是Android中提供的序列化方式。

2、優勢與劣勢

1) 整個讀寫全是在內存中進行,效率高,性能開銷小。
2) android 官方推薦的序列化方式。
3) 使用稍微麻煩,需要自己寫序列化、反序列化的相應代碼。
4) 序列化內存中首選,序列化到存儲存儲、網絡傳輸實現複雜麻煩。

2、實現Parcelable步驟

1)implements Parcelable 接口

2)重寫writeToParcel方法,將你的對象序列化爲一個Parcel對象,即:將類的數據寫入外部提供的Parcel 容器中,將需要傳遞的數據到Parcel容器保存,以便從 Parcel容器獲取數據。

3)重寫describeContents方法,內容接口描述,默認返回0,如果有文件描述符返回1。

4)實例化靜態內部對象CREATOR實現接口Parcelable.Creator

public static final Parcelable.Creator CREATOR

注:其中public static final一個都不能少,內部對象CREATOR的名稱也不能改變,必須全部大寫。需重寫本接口中的兩個方法:createFromParcel(Parcel in) 實現從Parcel容器中讀取傳遞數據值,封裝成Parcelable對象返回邏輯層,newArray(int size) 創建一個類型爲T,長度爲size的數組,僅一句話即可(return new T[size]),供外部類反序列化本類數組使用。

簡而言之:通過writeToParcel將你的對象映射成Parcel對象,再通過createFromParcel將Parcel對象映射成你的對象。也可以將Parcel看成是一個流,通過writeToParcel把對象寫到流裏面,在通過createFromParcel從流裏讀取對象,只不過這個過程需要你來實現,因此寫的順序和讀的順序必須一致。

Serializable、與Parcelable 的使用場景。

1)在內存序列化上,使用Parcelable序列化方式。

2)在將對象序列化到存儲設備、網絡上傳輸使用Serializable序列化方式。

代碼實踐:

  • Serializable
public class User implements Serializable {
    public String name;
    public int id;

    public User(String name, int id) {
        this.name = name;
        this.id = id;
    }
}
  • Parcelable
public class User2 implements Parcelable {

    public String name;
    public int id;

    public User2(String name, int id) {
        this.name = name;
        this.id = id;
    }


    /**
     * 反序列話的過程
     */
    public static final Creator<User2> CREATOR = new Creator<User2>() {

        // 從序列化的對象中創建原始對象
        @Override
        public User2 createFromParcel(Parcel in) {
            return new User2(in);
        }

        // 創建指定長度原始對象的數組
        @Override
        public User2[] newArray(int size) {
            return new User2[size];
        }
    };

    /**
     * 返回當前對象的內容描述
     *
     * @return 0 不返回 (幾乎所有情況)、1 返回
     */
    @Override
    public int describeContents() {
        return 0;
    }


    /**
     * 對象序列化寫到 Parcel 容器中
     *
     * @param dest  容器
     * @param flags 0 不返回(幾乎所有情況)、 1 表示當前對象需要作爲返回值返回,不能立即釋放資源
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(id);
    }

    /**
     * 對象反序列化 從Parcel 容器中讀取創建原始對象
     *
     * @param in 容器
     */
    protected User2(Parcel in) {
        name = in.readString();
        id = in.readInt();
    }
}

參考博客

https://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章