android 支持两种序列化:Serializable和Parcelble。前者是Java语言自带的序列化机制,通过读写文件实现对象的序列化和反序列化;后者是Android Os实现的序列化,它是通过读写内存来实现序列化,从而实现对象的传递。下面,就这两种方式详细说明。
Serializable
Serializable是Java提供的一个空接口。对象要想实现序列化,只需要如下:
public class SerializableClass implements Serializable{
private static final long serialVersionUID = 1L;
......
}
继承自Serializable,并且提供一个serialVersionUID即可。然后 通过对象输出流就可以实现序列化,通过对象输入流就可以实现反序列化。但是,需要注意的是:
- 静态成员不输入单个对象,不参与序列化;
- 使用transient关键字修饰的成员不参与序列化。
serialVersionUID用来在反序列化的时候做校验。反序列化时,会检测文件中的serialVersionUID和类的serialVersionUID是否一致,如果一致,则说明可以进行序列化,否则说明类的版本不匹配,不能进行序列化。
如果不指定serialVersionUID,在进行序列化的时候,会默认根据当前类的结构,生成hash值作为serialVersionUID写到文件,在反序列化的时候,同样会生成类的hash值并和文件中序列化写入的serialVersionUID进行比较,如果一致就可以序列化,否则不可以。这样会造成一个问题:如果序列化之后,类有了修改,那么,此时默认生成的hash值和之前序列化写入的hash值不匹配,导致无法序列化。
为了克服这个问题,最好手动指定serialVersionUID,或者由IDE工具自动生成。这样的好处是,及时序列化后,类做了小的改动,比如增加或删除了成员变量,那么,还是可以反序列恢复对象。但是,如果类的结构发生了非常规的改变,则无法反序列化,比如,修改了类名等。
Parcelable
Parcelable同样也是一个接口。它主要完成序列化和反序列化以及内容描述功能。User是一个Parcelable类:
public class User implements Parcelable{
public int userId;
public String userName;
public boolean isMale;
public Book book;
public User() {
}
public User(int userId, String userName, boolean isMale) {
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
}
/**
* 当当前对象中含有文件描述符时,返回1,其他时候返回0;
* @return
*/
public int describeContents() {
return 0;
}
/**
* 通过Parcel的write方法,实现序列化
* @param out
* @param flags
*/
public void writeToParcel(Parcel out, int flags) {
out.writeInt(userId);
out.writeString(userName);
out.writeInt(isMale ? 1 : 0);
out.writeParcelable(book, 0);
}
/**
* 实现反序列化
*/
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
/**
* 通过Parcel的read方法,实现反序列化生成一个对象
* @param in
* @return
*/
public User createFromParcel(Parcel in) {
return new User(in);
}
/**
* 实现反序列化生成一个数组
* @param size
* @return
*/
public User[] newArray(int size) {
return new User[size];
}
};
private User(Parcel in) {
userId = in.readInt();
userName = in.readString();
isMale = in.readInt() == 1;
/**
* book是一个Parcelable对象,反序列需要传递一个ClassLoader,否则会报错。
*/
book = in.readParcelable(Thread.currentThread().getContextClassLoader());
}
}
其中,序列化时通过writeToParcel()实现,反序列化通过CREATOR提供,内容描述由describeContents提供。注意事项见注释。系统为我们提供了很多Parcelable类:Intent,Bundle和BitMap等。同时,List和Map也可以是Parcelable的,当且仅当它们里面的每个对象都是Parcelable的。
Parcelable和Serializable虽然都是用来序列化的,但是,二者有较大差别。前者用来实现内存序列化,用来在Binder之间传递对象,效率较高,但是使用麻烦。后者是通过读写文件来实现序列化,需要大量的I/O操作,效率低,主要用来序列化对象到存储设备或者网络传送等。
本文深入探讨了Android中用于对象序列化的两种机制:Serializable和Parcelble。详细介绍了如何实现序列化与反序列化,包括静态成员、transient关键字以及serialVersionUID的作用。同时,对比了两者在内存序列化与文件序列化上的差异,以及它们在不同场景下的应用。
1004

被折叠的 条评论
为什么被折叠?



