Android面试题详解之序列Parcelable,Serializable的区别?

文章详细介绍了Android中Parcelable和Serializable两种序列化接口的原理与区别。Parcelable效率更高,适合内存传输,而Serializable简单但性能较低,适用于持久化存储或网络传输。实现Parcelable较为复杂,需要手动处理序列化和反序列化过程,而Serializable只需实现接口即可。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

序列Parcelable,Serializable的区别?(阿里)

详细讲解

架构师筑基必备技能《NDK专题-JNI实战篇》

这道题想考察什么?

掌握序列化接口实现原理,针对不同场景在工作中合理运用

考察的知识点

Parcelable原理

Serializable原理

考生应该如何回答

序列化 是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。Serializable是Java提供的序列化机制,而 Parcelable则是Android提供的适合于内存中进行传输的序列化方式。

Serializable

Serializable是Java中提供的一个 序列化接口,然而这个接口并没有任何方法需要实现者实现。

public interface Serializable {
}

这表示Serializable接口知识用来标识当前类可以被序列化与反序列化。

基本使用

实现了Serializable接口的类对象能够通过 ObjectOutputStream 将需要序列化数据写入到流中,因为 Java IO 是一种装饰者模式,因此可以通过 ObjectOutStream 包装 FileOutStream 将数据写入到文件中或者包装 ByteArrayOutStream 将数据写入到内存中。也可以通过 ObjectInputStream 从磁盘或者内存读取数据然后转化为指定的对象即可(反序列化)。

try {
	TestBean serialization = new TestBean("a","b");
    //序列化
	ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("/path/xxx"));
	os.writeObject(serialization);
	//反序列化
	ObjectInputStream is = new ObjectInputStream(new FileInputStream("/path/xxx"));
	TestBean deserialization = (TestBean) is.readObject();
} catch (IOException e) {
	e.printStackTrace();
}

实现了Serializable接口的类中成员属性除基本数据类型外,即引用类型,也需要实现Serializable接口,否则将在序列化时抛出java.io.NotSerializableException 异常。

public class TestBean implements Serializable {

    private String name;
    private String pwd;
    //Gson未实现Serializable接口,TestBean实例对象在序列化时抛出NotSerializableException
    private Gson gson = new Gson();
    public TestBean(String name, String pwd) {
        this.name = name;
        this.pwd = pwd;
    }

    public TestBean() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

}

因此,如果需要对某个类进行序列化时,对于类中不需要进行序列化与反序列化的属性,可以使用 transient 关键字声明。

private transient Gson gson = new Gson();
serialVersionUID

在实现了Serializable接口的类中,应该为此类定义一个serialVersionUID属性:

private static final long serialVersionUID = 1L; 

虽然不定义程序依然能够正常运行。 但是Java序列化的机制是通过判断类的serialVersionUID来验证的版本一致的。

序列化操作时会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会自动检测文件中的serialVersionUID,判断它是否与当前类中的serialVersionUID一致。如果一致说明序列化文件的版本与当前类的版本是一样的,可以反序列化成功,否则就失败。

例如在A程序中TestBean类的serialVersionUID=1L,而在程序B中TestBean类的serialVersionUID=2L。 那么A程序序列化输出的数据,在B程序中就无法反序列化为TestBean对象。

Parcelable

Parcelable是Android为我们提供的序列化的接口。相对于Java的Serializable,Parcelable的使用稍显复杂:

public class TestBean implements Parcelable {

    private String name;
    private String pwd;
    
    public TestBean(String name, String pwd) {
        this.name = name;
        this.pwd = pwd;
    }

    public TestBean() {
    }

    public int describeContents() {
    	return 0;
    }
    //序列化
	public void writeToParcel(Parcel out, int flags) {
		out.writeString(name);
         out.writeString(pwd);
	}
    public static final Parcelable.Creator<TestBean> CREATOR 
        = new Parcelable.Creator<TestBean>(){
        	public TestBean createFromParcel(Parcel in) {
				return new TestBean(in);
			}

			public MyParcelable[] newArray(int size) {
				return new TestBean[size];
			}
    }
    private TestBean(Parcel in) {
        // 反序列化:按序列化顺序读取
		name = in.readString();
		pwd = in.readString();
    }
}

Parcelable接口的实现类是通过Parcel写入和恢复数据的,并且必须要有一个非空的静态变量 CREATOR。

Parcel

Parcel其实就是一个数据载体,可以将序列化之后的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mbJWICkG-1686553360030)(images\parcel.png)]

Parcel可以读写原始数据类型,也可以读写实现了Parcelable对象。

因此Parcelable实现序列化的原理就是将一个完整的对象进行分解,而分解后的每一部分都是基本数据类型或者其他实现了Parcelable/Serializable的类型,从而实现传递对象的功能。

区别

Parcelable和Serializable都是实现序列化并且在Android中都可以使用Intent进行数据传递。Serializable是Java的实现方式,实现过程中会频繁的IO操作,但是实现方式简单。而Parcelable是Android提供的方式,效率比较高(号称比Serializable快10倍),但是实现起来复杂一些 。

如果只需要在内存中进行数据传输是,序列化应该选择Parcelable,而如果需要存储到设备或者网络传输上应该选择Serializable。这是因为Android不同版本Parcelable数据规则可能不同,所以不推荐使用Parcelable进行数据持久化。

更多面试题详解可以扫描二维码免费领取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值