Android序列化-Serializable接口
来源:互联网 发布:一键加群好友软件 编辑:程序博客网 时间:2024/05/16 23:02
场景,有一件礼物Gift(对象)我要把它送给远在国外的女票,怎么办?只能把这件礼物放在包裹里邮寄,女票收到之后在打开包裹得到这个礼物。那么我的理解Serializeable就是干这件事的。
Serializable是Java里面所提供的一个序列化接口,它只是一个空接口,内部并没有任何方法,是一个典型的标识接口(注1)。为我们提供了标准的序列化与反序列化操作。Serializable的使用非常简单,只要把想实现序列化的对象Gift 实现该接口,并添加下面一行代码就可以private static final long serialVersionUID=8712312312312321312L。其实serialVersoinUID也不是必须的,如果没有手动添加,那么也会自动生成一个。不过会对反序列化产生影响。下面我们看一个Gift实例:
public class Gift implements Serializable { public static final long serialVersionUID = 8098080809810941L; public String name; public int size; public float price; public Gift(String name, int size, float price) { this.name = name; this.size = size; this.price = price; } @Override public String toString() { return "Gift{" + "name='" + name + '\'' + ", size=" + size + ", price=" + price + '}'; }}通过Serializable实现序列化非常简单,实现完Serializable接口的Gift就是一个可以进行序列化与反序列化的对象。那么如何进行序列化和反序列化呢?也非常简单:
try { //序列化过程 Gift giftSrc = new Gift("lv", 20, 10000f); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/gift.txt")); out.writeObject(giftSrc); out.close(); //反序列化过程 ObjectInputStream in = new ObjectInputStream(new FileInputStream(Environment.getExternalStorageDirectory().toString() + "/gift.txt")); Gift giftSerial = (Gift) in.readObject(); in.close(); Log.e(TAG, "反序列化:" + giftSerial.toString()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }运行结果:
可以看到,和我们之前序列化的Gift对象内容一致。
上述序列化的过程:把实现了Serializable接口的Gift通过流写入到本地文件。
反序列的过程:通过流把本地文件中的内容读取出来,构建一个Gift对象,不过这时候的Gift对象与原来的Gift虽然内容一致,但是其本质并不是同一个对象。
serialVersionUID的作用:
serialVersionUID被称为序列化版本号,鉴别反序列时生成的类对象是不是之前序列化的类对象。
我们之前说过不手动生成serialVersonUID也是可以实现序列化的,只是对反序列化有些影响。那么我们就来详细的说一下手动和自动两种情况。
1.隐式:不手动生成,系统会根据类的结构自动生成其Hash值。而我们在序列化的时候会把生成serialVersionUID也一起写进本地文件。反序列化时系统会把之前写进去的serialVersionUID和之前写进去的做对比,如果一致,那么可以反序列化,如果不一致,那么反序列化失败Cash! 所以系统自动生成这种方式对对象的一致性要求很高,不能随意增删改。例如删除一个成员变量,那么系统会自动计算当前类的hash值并把它赋值给serialVersionUID,那么当前类的serialVersionUID就和反序列话中的不一致,造成反序列化失败。
2.显式:比如1L或者根据类名,接口名,成员方法以及属性等生成一个64为的hash并赋值给serialVersionUID,其余的参数我们可以进行修改,这种方式可以很大程度上避免反序列化的失败。
代码示例:在上面的基础上我们使用自动生成,序列化之后我们更改一个成员变量。
public static class Gift implements Serializable { // public static final long serialVersionUID = 8098080809810941L; public String name; public int size; public float price; public String place; public Gift(String name, int size, float price, String place) { this.name = name; this.size = size; this.price = price; this.place = place; } @Override public String toString() { return "Gift{" + "name='" + name + '\'' + ", size=" + size + ", price=" + price + ", place='" + place + '\'' + '}'; } }反序列化运行结果:很明显由于我们修改了Gift的成员变量,导致系统自动重新计算生成了一个新的serialVersionUID,其与反序列化中我们之前写进去的不同,所以不认为是同一个类,反序列化失败。
Tips:静态成员不属于类所以不参与序列化,transient关键字同样。
注1:标识接口是没有任何方法和属性的接口。标识接口不对实现它的类有任何语义上的要求,它仅仅表明实现它的类属于一个特定的类型。
标接口在Java语言中有一些很著名的应用,比如java.io.Serializable和java.rmi.Remote等接口便是标识接口。标识接口,当一个类实现了一个标识接口之后就像是给自己打了个标签。
打个比喻,不是很恰当。就像是一个人穿了件名牌衣服(实现了标识接口),别人一看他穿的衣服(标识接口)就知道他的品味、身份(特性)。0 0
- Android序列化-Serializable接口
- android序列化 Parcelable和Serializable接口
- Android使用序列化接口Parcelable、Serializable
- Android使用序列化接口Parcelable、Serializable
- Android使用序列化接口Parcelable、Serializable
- 序列化接口Serializable
- Serializable 序列化接口
- [Android] Android使用序列化接口Parcelable、Serializable
- [Android] Android使用序列化接口Parcelable、Serializable
- 可序列化接口 Serializable
- Serializable对象序列化接口
- 可序列化接口Serializable
- Serializable序列化接口作用
- java 序列化 Serializable接口
- 序列化(Serializable接口)
- 序列化接口:Serializable/Externalizable
- java序列化Serializable接口
- 序列化(Serializable接口)
- AndroidStudio 引入so包的两种方式
- scala 访问修饰符
- 【Java 对象和类】
- 数据结构
- 两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
- Android序列化-Serializable接口
- 浮点数不精确的问题
- Nginx配置SSL实现Https访问
- 连续邮资问题
- arrayList小心提防
- Hive MetaStore 源码分析
- pinyin4j获取汉字正确的全拼和简拼(解决多音字问题)
- 获取bat返回值
- 我的2016_To Code or Not to Code: No Question