作用:方便存储或传输,允许对象自定义外部存储格式。实现 Serializable(jdk自己) 或 Externalizable 接口(外部)。
概要:1序列化、2反序列化、3serialVersionUID作用、4父类序列化、5哪些字段会序列化、
6枚举序列化 7Externalizable序列化 8/9写入/读取时替换对象 9序列化场景 10Serializable和Externalizable区别
一、序列化
直接将对象写入流,调用 writeObject对某个对象写入,序列化自己,遍历寻找相关引用对象,自己和引用对象组成对象图关系都被序列化。
数组、enum、Class对象、ObjectStreamClass 和 String 都会做特殊处理,其他对象需实现 Serializable 或 Externalizable 接口。
二、反序列化
通过流直接读取对象,创建 FileInputStream 对象,输入文件为 tmp.o,创建 ObjectInputStream 嵌套前面输入流,调用 readObject 方法读对象(反序列:恢复对象、遍历完整对象图,创建对象图的所有对象)
三、serialVersionUID 有什么用
固定数值静态变量,验证版本一致性,反序列化时比较,版本一致成功:private static final long serialVersionUID = -6849794470754667710L;
自动生成,如不显示定义 serialVersionUID,由 JDK 生成(SHA 算法),用类名、类修饰符、接口名、字段、静态初始化信息、构造函数信息、方法名、方法修饰符、方法签名等
四、父类序列化什么情况
1)子类实现Serializable 接口而父类没实现,序列化子类时,子类属性状态会被写入而父类不被。2)父类也实现 Serializable 接口才能一起序列化。
3)父类未实现,生成对象会再调用父类构造函数,完成父类初始化(默认值)。Father 不序列化,反序列化时 Father 默认值0
五、哪些字段会序列化
两种方式决定哪些字段会被序列化:
1. 默认,非静态和非transient字段,将字段声明为 transient
2. ObjectStreamField 数组声明类要序列化的对象:约定只序列化 name 字段
六、枚举类型的序列化
与普通不同《 [从JDK角度认识枚举enum][JDK_enum]》。
1、被编译后会变成继承 java.lang.Enum 类(抽象),元素static final ,静态代码块 static{},生成 values 和 valueOf 两个方法。name 和 ordinal(位置索引 )
2、序列化:只name属性写入。反序列化:读name ,通过valueOf 找对应类型。
3、不能自定义 Enum 序列化, writeObject, readObject, readObjectNoData, writeReplace 及 readResolve ;serialPersistentFields 和 serialVersionUID 属性序列化时会被忽略,
提前设计好,很可能修改枚举类,导致反序列化失败。
七、Externalizable 接口作用
writeExternal 和 readExternal 方法,用户自己控制序列化内容,更灵活
序列化:writeExternal 写入 Date 对象,再写value
反序列化:readExternal 读取 Date 对象、value
八、写入时替换对象
writeReplace 实现,写入 Object 数组。反序列化转换为 Object 数组对象。
九、读取时替换对象
readResolve 方法实现的。readResolve 方法返回 2222,反序列化读2222。
十、序列化场景
1 远程通信(分布式传递对象,或者网络传输、EJB远程调用 )
2 本地存储(分布式存储,缓存存储等)
序列化可以保持对象的状态。典型的一个应用:tomcat关闭以后会把session对象序列化到SESSIONS.ser文件中,等下次启动的时候就把这些session再加载到内存里面来。
十一、Serializable和Externalizable的区别与联系
1、Externalizable继承Serializable;可通过 Serializable 的 writeReplace 和 readResolve 方指派替代对象
2、实现Externalizable必有默认构造方法。读入用无参构造器创建一个对象
3、Externalizable速度快,数据小,读取需自行实现