JavaSE -- 对象序列化和反序列化详细讲解
3. 对象序列化和反序列化
我在 Java 里面操作的对象都是存储在内存里面,当我们电脑关机这些对象就会丢失,如果要永久的保存(游戏存档)则必须远程传输到网络上或者保存到硬盘上,此时就需要使用对象序列化。当你要再次使用时,使用反序列化从文件或者网络中取出来。
注意:对象能够序列化和反序列化,一定要让对象实现下面两个接口中的一个
- Serializable
- Externalizable
3.1 对象序列化
使用 ObjectOutputStream 进行对象序列化
- 实现 Serializable 接口
- 执行对象序列化
3.2 对象反序列化
通过使用 ObjectInputStream 将文件或者网络中的字节序列恢复成 Java 对象的过程
-
简单使用(有错误)
这样直接序列化是有点问题得,因为要成功反序列化的前提是序列化和反序列化使用的序列化版本是一样的 ,不然会报错的。为了避免这个错误我们应该自己手动指定对象序列化版本号
-
解决错误
我们只要手动的加上这个序列化版本号(serialVersionUID)就可以了。
加入下面设置,就可以让 Idea 提醒你加上序列化版本号再去执行序列化,同时只要你点一下警告位置会自动生成一个序列化版本号
3.3 序列化应该注意的问题
- 当要执行序列化的对象的属性中有引用类型,该引用类型也要实现 Serializable 接口,不然会序列化失败
- 但是当我们引用的对象不是我们自己编写的无法修改代码,此时我们应该给该引用类型加上一个 transient 的标记,这样序列化是就会忽略掉该属性。
- 对象的类名,属性名和属性值都会被序列化,而方法,static 属性,transient 属性不会被序列化
3.4 使用 Externalizable 实现序列化和反序列化
Externalizable 是 Serializable 的子接口,要使用他则同样需要实现 Externalizable 接口,重写WriteExternal 和 ReadExternal 方法。可以自定义序列化过程。 static 和 transient 修饰变量也可以被序列化
在使用 Externalizable 执行序列化之前,我先说一下 Serializable 不足之处有哪些
- 序列化过程是递归,相对较慢
- 对于需要禁止序列化的属性,需要一个个加上 transient 关键修饰符,当属性较多时,比较繁琐
- 序列化和反序列化过程,中无法控制字段的序列化和反序列化方式
- 序列化过程中没有调用构造方法,当一些业务逻辑需要构造方法的参与时,Serializable 无法满足
-
实现接口和指定序列化版本和 Serializable 一样都要写
-
重写 writeExternal()
- 重写 ReadExternal()
- 使用 ObjectOutputStream 执行序列化的方法和 Serializable 一样