Android序列化和java序列化,Android序列化问题与思考

今天再来谈谈Android中的对象序列化,你了解多少呢?

序列化指的是什么?有什么用

序列化指的是讲对象变成有序的字节流,变成字节流之后才能进行传输存储等一系列操作。

反序列化就是序列化的相反操作,也就是把序列化生成的字节流转为我们内存的对象。

介绍下Android中两种序列化接口

Serializable

是Java提供的一个序列化接口,是一个空接口,专门为对象提供序列化和反序列化操作。具体使用如下:

public class User implements Serializable { private static final long serialVersionUID=519067123721561165l; private int id; public int getId() { return id; } public void setId(int id) { this.id = id; }}

实现Serializable接口,声明一个serialVersionUID。

到这里可能有人就问了,不对啊,平时没有这个serialVersionUID啊。没错,serialVersionUID不是必须的,因为不写的话,系统会自动生成这个变量。它有什么用呢?当序列化的时候,系统会把当前类的serialVersionUID写入序列化的文件中,当反序列化的时候会去检测这个serialVersionUID,看他是否和当前类的serialVersionUID一致,一样则可以正常反序列化,如果不一样就会报错了。

所以这个serialVersionUID就是序列化和反序列化过程中的一个标识,代表一致性。不加的话会有什么影响?如果我们序列化后,改动了这个类的某些成员变量,那么serialVersionUID就会改变,这时候再拿之前序列化的数据来反序列化就会报错。所以如果我们手动指定serialVersionUID就能保证最大限度来恢复数据。

Serializable的实质其实是是把Java对象序列化为二进制文件,然后就能在进程之间传递,并且用于网络传输或者本地存储等一系列操作,因为他的本质就存储了文件。可以看看源码:

private void writeObject0(Object obj, boolean unshared) throws IOException{ ... try { Object orig = obj; Class> cl = obj.getClass(); ObjectStreamClass desc; desc = ObjectStreamClass.lookup(cl, true); if (obj instanceof Class) { writeClass((Class) obj, unshared); } else if (obj instanceof ObjectStreamClass) { writeClassDesc((ObjectStreamClass) obj, unshared); // END Android-changed: Make Class and ObjectStreamClass replaceable. } else if (obj instanceof String) { writeString((String) obj, unshared); } else if (cl.isArray()) { writeArray(obj, desc, unshared); } else if (obj instanceof Enum) { writeEnum((Enum>) obj, desc, unshared); } else if (obj instanceof Serializable) { writeOrdinaryObject(obj, desc, unshared); } else { if (extendedDebugInfo) { throw new NotSerializableException( cl.getName() + "\n" + debugInfoStack.toString()); } else { throw new NotSerializableException(cl.getName()); } } } ...}private void writeOrdinaryObject(Object obj, ObjectStreamClass desc, boolean unshared) throws IOException { ... try { desc.checkSerialize(); //写入二进制文件,普通对象开头的魔数0x73 bout.writeByte(TC_OBJECT); //写入对应的类的描述符,见底下源码 writeClassDesc(desc, false); handles.assign(unshared ? null : obj); if (desc.isExternalizable() && !desc.isProxy()) { writeExternalData((Externalizable) obj); } else { writeSerialData(obj, desc); } } finally { if (extendedDebugInfo) { debugInfoStack.pop(); } } } public long getSerialVersionUID() { // 如果没有定义serialVersionUID,序列化机制就会调用一个函数根据类内部的属性等计算出一个hash值 if (suid == null) { suid = AccessController.doPrivileged( new PrivilegedAction() { public Long run() { return computeDefaultSUID(cl); } } ); } return suid.longValue(); }

可以看到是通过反射获取对象以及对象属性的相关信息,然后将数据写到了一个二进制文件,并且写入了序列化协议版本等等。

而获取·serialVersionUID·的逻辑也体现出来,如果id为空则会生成计算一个hash值。

Parcelable

Android自带的接口,使用起来要麻烦很多:需要实现Parcelable接口,重写describeContents(),writeToParcel(Parcel dest, @WriteFlags int flags),并添加一个静态成员变量CREATOR并实现Parcelable.Creator接口

public class User implements Parcelable { private int id; protected User(Parcel in) { id = in.read.........

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值