1. 为什么要实现Serializable序列化
主要有以下几个方面必须序列化
(1)想把的内存中的对象状态持久化保存到一个文件中或者数据库中时候。
具体比如使用ObjectInputStream 和 ObjectOutputStream 进行对象的读写。
/**
* 序列化
*/
private static void serializeFlyPig() throws IOException {
FlyPig flyPig = new FlyPig();
flyPig.setColor("black");
flyPig.setName("naruto");
flyPig.setCar("0000");
// ObjectOutputStream 对象输出流,将 flyPig 对象存储到E盘的 flyPig.txt 文件中,完成对 flyPig 对象的序列化操作
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("d:/flyPig.txt")));
oos.writeObject(flyPig);
System.out.println("FlyPig 对象序列化成功!");
oos.close();
}
(2)想把对象通过网络进行传播的时候。
(3)通过RMI(远程方法调用)传输对象的时候。
dubbo服务在调用的时候,传输的实体必须要实现序列化
(4)对象需要存储在session中时。
2. serialVersionUID是什么作用
系列化与反系列化中,是否允许反序列化,一个非常重要的一点是两个类的序列化 ID 是否一致
(就是 private static final long serialVersionUID = 1L),如果serialVersionUID不同,你将得到一个InvalidClassException异常。
serialVersionUID值有三种设置方法:
(1)没有明确的给这个 serialVersionUID 赋值,但是,Java会自动赋值的。这个值跟这个对象属性相关计算出来的
。这样的话容易导致序列化时的serialVersionUID值和反序列化的时候Java自动生成的这个serialVersionUID值是不同的(期间添加了新属性导致),导致异常。不推荐此法。
(2)一个是固定的 1L
如果没有特殊需求,就是用默认的 1L 就可以,这样可以确保代码一致时反序列化成功
(3)随机生成一个不重复的 long 类型数据(实际上是使用 JDK 工具生成)
有些时候,通过改变序列化 ID 可以用来限制某些用户的使用。客户端和服务端的serialVersionUID 都统一由服务端生成,那么服务端序列化后通过网络将二进制对象数据传给客户端,客户端负责反序列化得到对象,该模式可以使得客户端程序的使用需要服务器端的许可。
3. JavaBean是否真的需要实现Serializable
(1)疑问
- 一个对象返回给前端,那么该对象是否需要实现 Serializable接口。
- 前后端进行数据交互一般都是json格式的数据,那么是谁在什么时候将我们的对象转换成json格式的。
(2) 解答
SpringMVC框架返回一个json串给前端只需要将对象返回并且在方法上加上@ResponseBody注解。
原理是通过jackson将对象转换成json字符串。转换的过程中并没有调用对象的writeObject(java.io.ObjectOutputStream s) 来进行序列化。网络传输打交道的是SpringMVC转换后的json字符串
,实体对象与网络并没用直接的接触,所以这里的实体对象无需实现Serializable接口。
总结:对象需要网络传输或者持久化(对象直接转换为字节的形式
传输),那么就需要实现Serializable接口。如果只是转换为字符串的形式
与网络打交道,那么就不需要实现Serializable接口。
4.序列化和json区别
javaBean序列化在传输和存储有时会需要用到,JSON也是一样,他们有区别在哪里昵:
(1)长度的比较
serialize在编码后大概是json的两倍。
(2)速度的比较
serialize的速度在大数据量的情况下比json差了快一个数量级。
从上面两点看,json不管是在速度还是在生成的字符串的大小上都比serialize要好,那为什么serialize还要存在呢:json无法处理对象方法等数据。