您的位置:首页 > 其它

关于序列化的深入学习

2016-02-24 20:15 316 查看
关于序列化,我们最经常在android里面的遇到的情况是,当我们要把一个对象从一个activity传送到另一个activity时,我们必须实现序列化接口Serializable或者Parcelable,当然,在android上另一种常见的就是AIDL上的序列化的使用,为了更好地去学习AIDL,这里先对序列化先进行一个深入的学习,以便更好地掌握AIDL的用法。

序列化定义

java中的对象序列化的含义是将那些实现了Serializable接口的对象转换成一个字节序列,并能够将这个字节序列完全恢复成原来的对象,这也就是序列化的意义所在,这意味着序列化机制能自动弥补不同操作系统之间的差异。

我们再利用它的时候,可以实现“轻量级持久性”,其意味着一个对象的生存周期并不取决于程序是否进行,他可以生存与程序之间的调用。如:我们讲一个序列化对象写入磁盘,然后在重新调用程序时恢复该对象,就能够实现持久性的效果。

将对象序列化概念加入的java中是为了支持两种主要的特性:

java的远程调用(RMI)机制,他使存活在其他计算机的对象使用起来就像是存活于本机之中,当向远程对象发送消息时,需要通过对象序列化来传输参数和返回值。例如android中的AIDL机制,进行两个进程之间的通信。

在java中当我们使用一个Bean时候,一般情况下是在设计阶段对他的状态信息进行配置,这种状态信息必须保存起来,并在程序启动后期就行恢复,这个工作就由对象序列化完成,这里我们不对此情况进行多述。

使用方法

对于Serializable接口,我们只需要进行接口的实现,不用实现其他的方法,jvm帮我们自动实现序列化过程,实现简单代码如下:

public class Demo implements Serializable {

private int id=0;
private String string="demo";

public Demo(){

}
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getString() {
return string;
}

public void setString(String string) {
this.string = string;
}
}
//main方法

Demo demo=new Demo(1,"demo");
ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream("demo.txt"));
outputStream.writeObject(demo);
outputStream.close();

ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("demo.txt"));
Demo getDemo= (Demo) inputStream.readObject();
inputStream.close();


上述情况简单实现了如何进行对象存储的一个过程,我们通过ObjectOutputStream将对象通过writeObject写入到demo.txt中,然后通过ObjectInputStream从demo.txt中从新获取到对象,最后完成了序列化与反序列化的过程。

而在android中,多出了一个Parcelable方法,我们也可以通过这个方法进行序列化的过程,不过该过程比较繁琐,但是通过as我们可以自动进行代码的补充,示例代码如下:

public class Demo implements Parcelable {

private int id=0;
private String str="demo";

public Demo(int id,String s){
this.id=id;
str=s;

}

protected Demo(Parcel in) {
id = in.readInt();
str = in.readString();
}

public static final Creator<Demo> CREATOR = new Creator<Demo>() {
@Override
public Demo createFromParcel(Parcel in) {
return new Demo(in);
}

@Override
public Demo[] newArray(int size) {
return new Demo[size];
}
};

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getString() {
return str;
}

public void setString(String string) {
this.str = string;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(str);
}
}


writeToParcel方法是进行序列化的一个过程,而太监方法CREATOR则是进行反序列化的作用的,其中要注意在缺省构造函数时,我们必须手动添加上构造函数,因为Parcelable接口会要求实现一个参数为Parcel的构造函数,这里必须注意一下。

两种序列化方式的差别

Serializable接口是传统的java序列化接口,其中伴随着大量的I/O操作,而Parcelable是android中所特有的,唯一的缺点是使用起来稍微麻烦点,Parcelable主要用在内存序列化上,通过Parcelable将序列化到存储设备中或者将对象序列化后通过网络传输也可以,所以要选择哪种,大家可以凭喜好来决定了。

序列化的控制

当我们拥有特殊的需要那该如何处理,比如,我需要对象的某一部分不被实例化,这些情况下,针对java而言,我们可以通过两种方式进行:

使用Externalizable接口代替Serializable

使用transien关键字

Externalizable继承了Serializable接口,在Externalizable接口中,多了两个方法:

writeExternal()

readExternal()

这两个方法分别会在序列化和反序列华中进行自动的调用,以便执行一些特殊的操作,如果不想把某个变量进行序列化,我们就不必在writeExternal中进行传递,同理readExternal也不必进行读取。

transien关键字的作用是不让某个特定子对象进行序列化机制自动保存与恢复,如果子对象表示的是我们不希望将序列化敏感信息,例如密码。

对于Parcelable,我们可以通过writeToParcel进行相关变量的特殊处理,方法大体跟writeExternal一样,就不简述了。

参考资料:

《java编程思想》

《android艺术开发探索》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: