1. Serializable和Parcelable的定义
1.1 Serializable
package java.io;
public interface Serializable {
}
实现示例:
public class Person implements Serializable{
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
1.2 Parcelable
public interface Parcelable
{
//内容描述接口,基本不用管
public int describeContents();
//写入接口函数,打包
public void writeToParcel(Parcel dest, int flags);
//读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数传入
//为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例
public interface Creator<T>
{
public T createFromParcel(Parcel source);
public T[] newArray(int size);
}
}
实现示例:
public class Person implements Parcelable{
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
//这里的读的顺序必须与writeToParcel(Parcel dest, int flags)方法中写的顺序一致
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
//这里的读的顺序必须与writeToParcel(Parcel dest, int flags)方法中写的顺序一致,否则数据会有差错
public Person(Parcel source) {
name = source.readString();
age = source.readInt();
}
//这里默认返回0即可
@Override
public int describeContents() {
return 0;
}
//把值写入Parcel中
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
//供外部类反序列化本类数组使用
@Override
public Person[] newArray(int size) {
return new Person[size];
}
//从Parcel中读取数据
@Override
public Person createFromParcel(Parcel source) {
return new Person(source);
}
};
}
Serializable实现与Parcelabel实现的区别
a. Serializable的实现,只需要implements Serializable即可。这只是给对象打了一个标记,系统会自动将其序列化。
b. Parcelabel的实现,不仅需要implements Parcelabel,还需要在类中添加一个静态成员变量CREATOR,这个变量需要实现Parcelable.Creator接口。
2. implements Serializable和Parcelabel的意义
2.1 implements Serializable的意义
对象什么时候需要进行序列化?
a. 当你想把的内存中的对象写入到硬盘的时候
例如:内存不够用了,那计算机就要将内存里面的一部分对象暂时的保存到硬盘中,等到要用的时候再读入到内存中,硬盘的那部分存储空间就是所谓的虚拟内存。在比如过你要将某个特定的对象保存到文件中,我隔几天在把它拿出来用,那么这时候就要实现Serializable接口。
b. 当你想用套接字在网络上传送对象的时候
例如:在进行Java的Socket编程的时候,你有时候可能要传输某一类的对象,那么也就要实现Serializable接口。最常见的你传输一个字符串,它是JDK里面的类,也实现了Serializable接口,这样做为的是将数据变为二进制来传输,所以可以在网络上传输。
c. 当你想通过RMI传输对象的时候
例如:如果要通过远程的方法调用(RMI)去调用一个远程对象的方法,如在计算机A中调用另一台计算机B的对象的方法,那么你需要通过JNDI服务获取计算机B目标对象的引用,将对象从B传送到A,就需要实现序列化接口。
一个类只有实现了Serializable接口,它的对象才是可序列化的。因此如果要序列化某些类的对象,这些类就必须实现Serializable接口。而实际上,Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。
例如:
public class Test implements Serializable{
private int id;
private String name;
……
}
如果没有用implements Serializable时,数据以此Test对象封装存进数据库,当要取出时,即使SQL在数据库中能正确返回数据,但sessionFactory.getCurrentSession().createNativeQuery(SQL,Test.class).list()返回的数据中字段内容都是空(数据条目数量正常不受影响),从而会导致诸如Method threw ‘javax.persistence.PersistenceException’ exception.等错误。
总结:implements Serializable的意义是实现序列化,保证数据完璧归赵的取或读。
2.2 implements Parcelabel的意义
implements Parcelabel的意义和implements Serializable相同,都是实现序列化,区别如下:
a. 在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
b. Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
c. Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable。
总结:
实现Serializable和Parcelable都是为了实现序列化,二者的区别体现在两个地方:
a. 实现Serializable接口非常简单,声明一下就可以了;但是实现Parcelable需要重写writeToParcel方法、重写describeContents方法、实例化静态内部对象CREATOR实现接口Parcelable.Creator
b. 在使用内存的时候,Parcelable比Serializable性能高,因此推荐使用Parcelable。
好文:
https://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html
https://blog.csdn.net/am540/article/details/82498298