Java序列化版本号的作用

😋 最前

实体类中常见到

1
private static long serialVersionUID = 1L;

它表示Java序列化版本号

先简单解释两者的含义:

序列化:将Java对象转化为字节,然后进行网络传输或持久化到磁盘

反序列化:将本地或网络传输来的字节转化为Java对象

⭐️ 具体场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
** 用户实体类V1
**/
@Data
public class User {

private String name;
private Character sex;
private Integer age;

public static void main(String[] args) throws IOException {
// 写入磁盘
InputStream fin = new FileInputStream("D:\\code\\test.txt");
ObjectInputStream oin = new ObjectInputStream(fin);
oin.writeObject(new User("huanghao"));
oin.close();
fin.close();

// 读取磁盘
OutpuStream fout = new FileOutputStream("D:\\code\\test.txt");
ObjectOutpuStream oout = new ObjectOutpuStream(fout);
User user = (User)oout.readObject();
System.out.println(user);
oout.close();
fout.close();
}
}

看上去没问题,但假如User类升级,该类V1版本是三个属性字段(name,sex,age),V2版本时新增一个属性字段(salary),在V1版本时写入磁盘,在V2版本时读取磁盘,则会报InvalidClassException异常,就好比手中的旧船票已经登不上新客船。

🌈 解决方案

User类虽升级,但并不该影响序列化与反序列化(可理解为写入,升级后还能成功读出)。如何解决?引入版本号serialVersionUID即可。引入该类需要实现接口Serializable(本质是在告诉JDK该类要序列化)

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
** 用户实体类V2
**/
@Data
public class User implements Serializable{

private static long serialVersionUID = 1234567890123456789L;

private String name;
private Character sex;
private Integer age;
private Double salary;
}

(ps:IDEA有自动生成版本号的选项,自行百度)

⛄️ 更多

如果想在序列化时屏蔽某字段,可用transient关键字来修饰

1
private transient Double salary;

这样一来,salary虽然还在实体类中,但salary不会被写入到本地磁盘的文件中


Java序列化版本号的作用
http://example.com/2022/09/17/Java序列化版本号的作用/
作者
HuangHao
发布于
2022年9月17日
许可协议