1、序列化的目的

(1)永久的保存对象数据(将对象数据保存到文件或磁盘中);

(2)通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的,因此序列化的目的是将对象数据转化成字节流的形式);

(3)将对象数据在进程之间进行传递(Activity之间传递对象数据时,需要在当前的Activity中对对象数据进行序列化操作,在另一个Activity中需要进行反序列化操作将对象数据取出);

(4)Android中,使用Intent在Activity之间传递数据的时候,基本数据类型直接进行相关传递即可,但是一旦数据类型比较复杂的时候就不需要进行序列化操作了。

2、使用Serializable进行序列化

使用Serializable进行序列化的代码如下:

public class UserSerializable implements Serializable {
private static final long serialVersionUID = 1L; public int userId;
public String userName;
public boolean isMale; public UserSerializable(int userId, String userName, boolean isMale) {
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
}
}

Serializable是Java所提供的一个序列化接口,它是一个空接口,为对象提供标准的序列化和反序列化的操作。使用Serializable来实现序列化相当简单,只需要在类的声明中指定一个 serialVersionUID 即可自动实现默认的序列化过程。

声明了类定义之后,我们可以通过ObjectOutputStream和ObjectInputStream来轻松实现序列化和反序列化操作,针对上面的 UserSerializable 类的操作代码如下:

// 序列化过程
UserSerializable user = new UserSerializable(1, "Jack", true);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
out.writeObject(user);
out.close(); // 反序列化过程
ObjectInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
UserSerializable newUser = (UserSerializable)in.readObject();
in.close();

注意:序列化的对象和反序列化出来的对象中的内容完全一样,但是两者并不是同一个对象。

下面来解释一下serialVersionUID的含义。serialVersionUID是用来辅助序列化和反序列化过程的,原则上序列化后的数据中的serialVersionUID只有和当前类的serialVersionUID相同才能够正常地被反序列化。

serialVersionUID的工作机制:序列化的时候,系统会把当前类的serialVersionUID写入序列化的文件中(也可能是其他中介),当反序列化的时候系统会去检测文件中的serialVersionUID,看它是否和当前类的serialVersionUID一致,如果一致就说明序列化的类的版本和当前类的版本是相同的,这个时候可以成功的反序列化;否则就说明当前类和序列化的类相比发生了某些改变(如成员变量的数量、类型发生改变),这个时候就无法正常的序列化了。

一般来说,我们可以自己显式地手动指定serialVersionUID的值(随便一个long类型的值即可),这样的话,不管类中的数据怎样变化,最终存储到文件(或其他中介)中的serialVersionUID的值都不会改变,因此可以最大限度的保证序列化和反序列化过程的成功;而如果不显式地指定serialVersionUID,则每次系统都会根据类的结构生成一个hash值并赋值给serialVersionUID,因此当类结构发生改变后,就可能造成反序列化过程失败。

注意:
(1)静态成员变量和用transient关键字修饰的变量不参与序列化过程;
(2)如果类结构发生了非常规性改变,比如修改了类名、修改了成员变量的类型,这个时候尽管serialVersionUID验证通过了,但是反序列化操作还是会失败,因为类结构有了毁灭性的改变;
(3)使用Serializable进行序列化是使用反射机制实现的,会产生很多临时变量;
(4)序列化过程知识针对变量进行序列化,不会针对方法进行序列化。

3、使用Parcelable进行序列化

使用Parcelable进行序列化的代码如下:

public class UserParcelable implements Parcelable {
public int userId;
public String userName;
public boolean isMale; public Book book; public UserParcelable(int userId, String userName, boolean isMale, Book book) {
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
this.book = book;
} // 从序列化后的对象中反序列化出原始对象
protected UserParcelable(Parcel in) {
this.userId = in.readInt();
this.userName = in.readString();
this.isMale = in.readInt() == 1;
this.book = in.readParcelable(Thread.currentThread().getContextClassLoader());
} // 反序列化
public static final Creator<UserParcelable> CREATOR = new Creator<UserParcelable>() {
@Override
public UserParcelable createFromParcel(Parcel in) {
return new UserParcelable(in);
} @Override
public UserParcelable[] newArray(int size) {
return new UserParcelable[size];
}
}; // 返回当前对象的内容描述,几乎在所有情况下都返回 0
@Override
public int describeContents() {
return 0;
} // 序列化,将当前对象写入到序列化结构中,flags 参数在几乎所有情况下都为 0
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(userId);
dest.writeString(userName);
dest.writeInt(isMale ? 1 : 0);
dest.writeParcelable(book, 0);
}
}

Parcelable也是一个接口,只要实现这个接口,一个类的对象就可以实现序列化并可以通过Intent和Binder传递。

从上面的示例代码中可以看到, writeToParcel() 方法用来进行序列化; Creator<UserParcelable> 用来反序列化(可以反序列化成对象或对象数组); describeContents() 方法用来进行内容描述(一般都会返回0)。

在上面的代码中,UserParcelable类中除了int、String、boolean三种基本数据类型之外,还有一个自定义的bean类Book,如果想要对Book对象也进行序列化和反序列化,则Book类必须也实现Parcelable接口,且在序列化和反序列化的时候,调用 readParcelable() 方法和 writeParcelable() 方法。

Parcelable的工作原理:
(1)在Parcelable的操作中,无论读还是写,都需要使用Parcel作为中间层进行数据传递;
(2)Parcel涉及到的东西和C++底层有关,整个读写全是在内存中进行,主要通过 malloc() 、 realloc() 、 memcpy() 等内存操作进行,因此效率会比使用Serializable高很多。

注意:使用Parcelable可以保证反序列化出来的对象就是原来的对象,而不是重新new出来的对象。

4、两种方法的比较

(1)Serializable是Java中的序列化接口,而Parcelable是Android中的序列化接口;

(2)Serializable使用了反射机制,在序列化操作的时候会产生大量的临时变量,从而导致GC的频繁调用;Parcelable是以IBinder作为信息载体的,在内存上开销比较小,因此在内存的使用和性能方面,Parcelable会稍强于Serializable;

(3)在读写数据的时候,Serializable是通过I/O流的形式在磁盘上进行数据的读写,而Parcelable则是在内存中进行数据的读写;

(4)虽然使用Parcelable比使用Serializable麻烦,但它的效率很高,因此在很多情况下都推荐使用Parcelable;

(5)在不同的Android版本中,Parcelable可能会不同,因此Parcelable可能不能将数据持久化,也就是说,如果要想对数据进行持久化操作,还是需要使用Serializable。

【Android - IPC】之Serializable和Parcelable序列化的更多相关文章

  1. Android中Serializable和Parcelable序列化对象详解

    学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Parcelable进行序列化操作 5.P ...

  2. Android开发之Serializable 和 Parcelable的差别(源码分享)

    android 中自己定义的对象序列化的问题有两个选择一个是Parcelable,另外一个是Serializable. 一 序列化原因: 1.永久性保存对象.保存对象的字节序列到本地文件里. 2.通过 ...

  3. android ipc通信机制之二序列化接口和Binder

    IPC的一些基本概念,Serializable接口,Parcelable接口,以及Binder.此核心为最后的IBookManager.java类!!! Serializable接口,Parcelab ...

  4. Android序列化之Serializable和Parcelable

    PS:还有几天就开学了.先来一发. 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Par ...

  5. android Activity之间数据传递 Parcelable和Serializable接口的使用

    Activity之间传数据时,为了避免麻烦,往往会将一些值封装成对象,然后将整个对象传递过去.传对象的时候有两种情况,一种是实现Parcelable接口,一种是实现Serializable接口.0.解 ...

  6. android中实现Parcelable序列化步骤

    import java.io.Serializable; import java.text.DecimalFormat; import android.os.Parcel; import androi ...

  7. Android中Parcelable序列化总结

    在使用Parcelable对android中数据的序列化操作还是比较有用的,有人做过通过对比Serializable和Parcelable在android中序列化操作对象的速度比对,大概Parcela ...

  8. 浅谈Android中Serializable和Parcelable使用区别

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.概述 Android开发的时候,我们时长遇到传递对象的需求,但是我们无法将对象的引用传给Activity或者Fragment,我们需要将这些对象 ...

  9. 序列化Serializable和Parcelable

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 简单记录下序列化Serializable和Parcelable的使用方法. Android中Intent如果要传递类对象,可以通过两 ...

随机推荐

  1. js 的隐式转换与显式转换

    隐式转换   1.undefined与null相等,但不恒等(===) 2.一个是number一个是string时,会尝试将string转换为number 3.隐式转换将boolean转换为numbe ...

  2. VMware Workstation 12 一些可用的序列号

    任选一个即可: VF5XA-FNDDJ-085GZ-4NXZ9-N20E6 UC5MR-8NE16-H81WY-R7QGV-QG2D8 ZG1WH-ATY96-H80QP-X7PEX-Y30V4 AA ...

  3. SpringBoot + Redis 执行lua脚本

    1.背景 有时候,我们需要一次性操作多个 Redis 命令,但是 这样的多个操作不具备原子性,而且 Redis 的事务也不够强大,不支持事务的回滚,还无法实现命令之间的逻辑关系计算.所以,一般在开发中 ...

  4. QHDYZ模拟赛20191012

    今天信息处老师(并不是教练,基本等于机房看门大爷) (好吧老师其实很犇,软件什么的厉害的一批,只是不能带oi--) 跟我说:"xxj,过两天月考完了,可以在初赛前再整一次模拟赛,一天,三道题 ...

  5. Nginx篇--最初级用法web

    最近很久都没有写博客了,一来主要是时间不够每天回到家都接近晚上11点了,但是以后每天还是保证一篇随笔.好用来整理总结自己的知识. web服务器很有多例如:Apache nginx tengine li ...

  6. Redis实战--Redis整合SpringBoot示例

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 该文章 ...

  7. 用python实现你的绘画梦想

    导语: ​ 你是否还在为当时年少时没有选择自己的梦想而伤心,是否还在为自己的无法成为绘画名家而苦恼,这一切都不需要担心.python都能帮你实现,诶!python怎么能画画呢,一些简单的图案没问题,但 ...

  8. raw文件转mha文件

    raw格式 在体数据(volume)中,经常会遇到raw文件,raw文件就是其实就是所有体素组成的文件,raw文件必须还有一些描信息才能用(因为得知道数据的size,type,spacing等),就像 ...

  9. Android9.0 SystemUI 网络信号栏定制修改

    前情提要 Android 8.1平台SystemUI 导航栏加载流程解析 9.0 改动点简要说明 1.新增 StatusBarMobileView 替代 SignalClusterView,用以控制信 ...

  10. kubespray2.11安装kubernetes1.15

    关于kubespray Kubespray是开源的kubernetes部署工具,整合了ansible,可以方便的部署高可用集群环境,官网地址:https://github.com/kubernetes ...