什麼是序列化?
序列化就是把對象的信息轉換成可存儲,可傳輸的狀態,序列化後的對象可以存儲在臨時或持久化持久性儲存區或者在網絡中傳輸
有序列化也有反序列化,反序列化就是從存儲區讀取序列化後對象,重新創建該對象.
Serializable 與 Parcelable 的區別?
先說一下Seralizable 吧
Serializabe是Java提供的可序列化的接口,當我們點進這個接口一看就會發現這個接口裏面啥也沒有,嗯,這是一個空接口
Serializable使用起來很簡單就是讓序列化的類實現這個接口就可以默認幫我們實現序列化了;這時候就有疑問了, 實現一個空接口咋就序列化了?實現Serializable就是給對象一個標識,有了這個標識的對象就默認給序列化了,我們要做的就是根據自己的需求傳輸或者存儲這個對象. 這裏我們可以通過I/O流的方式讀取或者存儲序列化的對象
到這裏就不得不說serialVersionUID;serialVersionUID不是必須的,可以指定也可以不指定;如果沒有爲類指定serialVersionUID,則JVM會自動根據類的內容生成一個serialVersionUID,類中的任何變化均會導致serialVersionUID的變化,如新增一個空格。
因此,若一個類沒有指定serialVersionUID,而且發生了變化,則讀取磁盤中的對象時就會報錯。
指定serialVersionUID的話 序列化數據中的serialVersionUID 與當前類中的serialVersionUID相同纔可以被反序列化,也就是說我們指定sserialVersionUID之後很大程度上避免了反序列化失敗,指定了SerialVersionUID之後,如果我們的類發生了改變比如增加了一些成員變量或者刪除了一些成員變量,只要SerialVersionUID一致,我們仍然可以反序列化成功,這樣就可以最大程度的恢復數據
Parcelable
Parcelable也是用來實現序列化的,也是一個接口,但Parcelable不是空接口了,Parcelable是android特有的,下面來看一下Parcelable裏面都有哪些東西
打開Parcelable接口可以看到裏面:
public interface Parcelable
{
//內容描述接口,基本不用管
public intdescribeContents();
//寫入接口函數,打包
public voidwriteToParcel(Parcel dest, int flags);
//讀取接口,目的是要從Parcel中構造一個實現了Parcelable的類的實例處理。因爲實現類在這裏還是不可知的,所以需要用到模板的方式,繼承類名通過模板參數傳入
//爲了能夠實現模板參數的傳入,這裏定義Creator嵌入接口,內含兩個接口函數分別返回單個和多個繼承類實例
publicinterface Creator<T>
{
publicT createFromParcel(Parcel source);
publicT[] newArray(int size);
}
}
Parcelable的實現
實現Parcelable 步驟
1) implements Parcelable
2) 重寫 writeToParcel 方法,將你的對象序列化爲一個Parcel對象,即:將類的數據寫入外部提供的parcel中,打包需要傳遞的數據到Parcel容器保存,以便從Parcel容器中獲取數據
3) 重寫describeContents()方法,內容接口描述,默認返回0就可以
4) 實例化內部靜態對象CREATOR實現接口Parcelable.Creator
| publicstaticfinal Parcelable.Creator<T> CREATOR |
這要注意,其中public staticfinal一個都不能少,內部對象CREATOR的名稱也不能改變,必須全部大寫。需重寫本接口中的兩個方法:
createFromParcel(Parcel in) 實現從Parcel容器中讀取傳遞數據值,封裝成Parcelable對象返回邏輯層,newArray(
int size)
創建一個類型爲T,長度爲size的數組,僅一句話即可(returnnewT[size]),供外部類反序列化本類數組使用。
簡而言之:通過writeToParcel將你的對象映射成Parcel對象,再通過createFromParcel將Parcel對象映射成你的對象。也可以將Parcel看成是一個流,
通過writeToParcel把對象寫到流裏面,在通過createFromParcel從流裏讀取對象,只不過這個過程需要你來實現,因此寫的順序和讀的順序必須一致。
實現代碼如下:
public class MyParcelable implements Parcelable
{
privateint mData;
publicint describeContents()
{
return 0;
}
publicvoid writeToParcel(Parcel out, int flags)
{
out.writeInt(mData);
}
publicstatic final Parcelable.Creator<MyParcelable> CREATOR = newParcelable.Creator<MyParcelable>()
{
public MyParcelable createFromParcel(Parcel in)
{
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size)
{
return new MyParcelable[size];
}
};
privateMyParcelable(Parcel in)
{
mData = in.readInt();
}
}
選擇序列化方法的原則
1)在使用內存的時候,Parcelable比Serializable性能高,所以推薦使用Parcelable。
2)Serializable在序列化的時候會產生大量的臨時變量,從而引起頻繁的GC。
3)Parcelable不能使用在要將數據存儲在磁盤上的情況,因爲Parcelable不能很好 的保證數據的持續性在外界有變化的情
況下。儘管Serializable效率低點,但此時還是建議使用Serializable。