序列化与反序列化
https://baijiahao.baidu.com/s?id=1709082440305850192&wfr=spider&for=pc
https://mp.weixin.qq.com/s/j0gYgWT5tWwU8G7M2GmX2g
1.序列化概念
什么是序列化和反序列化
把对象转化成二进制数据的过程称为序列化,把二进制数据转化成对象的过程称为反序列化。
什么时候需要用到序列化
- 当我们需要将内存中的对象持久化到磁盘、数据库中时
- 当我们需要与浏览器进行交互时
- 当我们需要实现PRC时
结论:只要我们对内存中的对象进行持久化或网络传输时,需要序列化和反序列化。
2.哪里用到了序列化
这里就会有一下疑惑,我在平时的接口开发的时候并没有用到什么序列化啊!
String源码
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
}
JSON格式实际上就是一个将对象转化成字符串,所以服务器和浏览器交互时其实就是字符串。String类型实现了Serializable接口,并显示指定UID的值。
当我们将对象持久化到数据量中时,只是将对象中的属性持久化到数据库中,而这些属性都实现了Serializable接口的基本属性。
3.什么是RPC
远程服务调用:HTTP调用、RPC调用
HTTP调用:HttpClient.get(url, param…)
RPC调用:屏蔽远程调用网络相关的细节,具体就是RPC会给接口生成一个代理类,由代理类来触发远程调用,这样我们调用远程接口就无感知了。
-
服务调用方,面向接口编程,利用动态代理屏蔽底层调用细节将请求参数、接口等数据组合起来并通过序列化转化为二进制数据,再通过 RPC 协议的封装利用网络传输到服务提供方。
-
服务提供方,根据约定的协议解析出请求数据,然后反序列化得到参数,找到具体调用的接口,然后执行具体实现,再返回结果。
-
这里面还有很多细节。比如请求都是异步的,所以每个请求会有唯一 ID,返回结果会带上对应的 ID,这样调用方就能通过 ID 找到对应的请求塞入相应的结果。
4.为什么要实现Serialiable接口
在 Java 中实现了 Serializable 接口后,JVM 会在底层帮我们实现序列化和反序列化,如果我们不实现 Serializable 接口,那自己去写一套序列化和反序列化代码也行。
5.为什么要指定UID
当然可以不指定UID,JVM在序列化时会根据属性自动生成一个UID,然后与属性一起序列化,再进行持久化或网络传输。在反序列化时,JVM会再根据属性自动生成一个新版UID,饭后将新UID和旧UID进行比较,相同则反序列化成功,否则则报错。
这样容易出一个问题,在实际开发中,如果这个类的属性修改了,那么旧对象反序列化就会报错。所以我们需要指定一个UID,保证不变就行了。
6.Java序列化的其他特性
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private Integer age;
private transient String sex;
private static String signature = "你眼中的世界就是你自己的样子";
}
被transient关键字修饰的属性不会被序列化,static属性也不会被序列化。
为什么static属性不会被序列化?
因为序列化是针对对象而言的, 而 static 属性优先于对象存在, 随着类的加载而加载, 所以不会被序列化.
看到这个结论, 是不是有人会问, serialVersionUID 也被 static 修饰, 为什么 serialVersionUID 会被序列化? 其实 serialVersionUID 属性并没有被序列化, JVM 在序列化对象时会自动生成一个 serialVersionUID, 然后将我们显示指定 的 serialVersionUID 属性值赋给自动生成的 serialVersionUID.