本文目标:开发人员,在了解serialVersionUID作用的条件下,进行序列化相关类的定义操作,达到版本可控的程度。
文章目录
- 1 场景
- 2 要点
- 2.1 类要实现Serializable接口
- 2.2 类中的serialVersionUID版本要一致
- 3 总结/练习
1 场景
Java中的序列化主要应用于以下3个场景:
(1)对象状态持久化 - 将对象保存到文件或数据库中
(2)网络传输优化 - 通过序列化减少网络传输数据量
(3)RPC等的应用基础 - 远程过程调用需要以流的形式处理请求和响应
本文以将对象保存到文件举例,说明serialVersionUID在序列化、反序列化中,如何起到版本控制的作用。
首先一起来看正常情况下,Apple对象如何进行序列化,得到二进制数据存入文件;以及如何读取文件,将二进制数据反序列化得到Apple对象。
1.1 Apple类定义
要进行序列化的对象,对应类需要实现Serializable接口,未实现该接口,无法进行序列化。
serialVersionUID的1L,也会参与序列化,表示版本。
java">package maplegam.com;import java.io.Serializable;public class Apple implements Serializable {private static final long serialVersionUID = 1L;String name;String weight;public Apple(String name, String weight) {this.name = name;this.weight = weight;}public String getName() {return this.name;}public void setName(String name) {this.name = name;}public String getWeight() {return this.weight;}public void setWeight(String weight) {this.weight = weight;}}
1.2 apple对象序列化并存入文件
使用java io库的ObjectOutputStream进行序列化处理,并将结果存入“abc.txt”文件。
java">package maplegam.com;import java.io.*;public class SerialzableTest {public static void main(String[] args) throws Exception {String writerPath = "D:\\abc.txt";ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(writerPath, true));oos.writeObject(new maplegam.com.Apple("aaa", "3.78"));oos.close();}
}
abc.txt文件内容如下图所示:
序列化文件内容" />
1.3 读取文件反序列化得到apple对象
使用java io库的ObjectInputStream进行反序列化处理,并将得到的apple对象内容打印出来。
java">package maplegam.com;import java.io.FileInputStream;
import java.io.ObjectInputStream;public class SerialzableReadTest {public static void main(String[] args) throws Exception {String writerPath = "D:\\abc.txt";ObjectInputStream ois = new ObjectInputStream(new FileInputStream(writerPath));Object oj = ois.readObject();Apple apple = (Apple) oj;System.out.println("Apple name:"+apple.getName());System.out.println("Apple weight:"+apple.getWeight());ois.close();}
}
2 要点
Serializable_103">2.1 类要实现Serializable接口
进行序列化的类,没有实现Serializable接口时,会出现报错“java.io.NotSerializableException”。
2.2 类中的serialVersionUID版本要一致
serialVersionUID版本如果不一致(比如序列化时客户端引用的该类版本为1L,服务端引用的该类版本为2L),会出现报错“java.io.InvalidClassException: maplegam.com.Apple; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2”。
3 总结/练习
在需要序列化的类中,声明serialVersionUID是一个好习惯,能提高代码阅读效率。
在代码走查阶段,如果发现客户端、服务端该值不一样,就能提前发现问题,不用等到上线报错后,从日志中看出是该问题。
可以参照前“1 场景”、“2 要点”内容,尝试在序列化过程中,声明serialVersionUID,查看版本一致、不一致的不同处理结果。