java android 序列号serializable和parcelable

Posted luzhouxiaoshuai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java android 序列号serializable和parcelable相关的知识,希望对你有一定的参考价值。

why

为什么要了解序列化?—— 进行android开发的时候,无法将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递。

what

什么是序列化 —— 序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

how

怎么通过序列化传输对象?

Android中Intent如果要传递类对象,可以通过两种方式实现。

方式一:Serializable,要传递的类实现Serializable接口传递对象,
方式二:Parcelable,要传递的类实现Parcelable接口传递对象。
Serializable(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

Parcelable(android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,
而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

实现Parcelable的作用

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

应用场景

需要在多个部件(Activity或Service)之间通过Intent传递一些数据,简单类型(如:数字、字符串)的可以直接放入Intent。复杂类型必须实现Parcelable接口。

serializable和下面几个问题需要注意的:

public class Test implements Serializable {

    private static final long serialVersionUID = 1L;

    public static int staticVar = 5;

    public static void main(String[] args) {
        try {
            //初始时staticVar为5
            ObjectOutputStream out = new ObjectOutputStream(
                    new FileOutputStream("result.obj"));
            out.writeObject(new Test());
            out.close();

            //序列化后修改为10
            Test.staticVar = 10;

            ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
                    "result.obj"));
            Test t = (Test) oin.readObject();
            oin.close();
            
            //再读取,通过t.staticVar打印新的值
            System.out.println(t.staticVar);
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

清单 2 中的 main 方法,将对象序列化后,修改静态变量的数值,再将序列化对象读取出来,然后通过读取出来的对象获得静态变量的数值并打印出来。依照清单 2,这个 System.out.println(t.staticVar) 语句输出的是 10 还是 5 呢?

最后的输出是 10,对于无法理解的读者认为,打印的 staticVar 是从读取的对象里获得的,应该是保存时的状态才对。之所以打印 10 的原因在于序列化时,并不保存静态变量,这其实比较容易理解,序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。

案例2:

ransient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

 







以上是关于java android 序列号serializable和parcelable的主要内容,如果未能解决你的问题,请参考以下文章

ObjectOutputStream和ObjectInputStream对对象进行序列化和反序列化

使用不可序列化的对象序列化 hashmap

尽管验证失败,但尝试序列化对象

Kotlinx 序列化,避免在其他数据类型上崩溃

将 ISerializable 与 DataContractSerializer 一起使用时,如何阻止序列化程序输出类型信息?

java android 序列号serializable和parcelable