Java中序列化接口Serializable的serialVersionUID的作用

╰半橙微兮° 2023-09-23 14:42 255阅读 0赞

原文网址:Java中序列化接口Serializable的serialVersionUID的作用_IT利刃出鞘的博客-CSDN博客

简介

本文介绍Java中序列化接口Serializable的serialVersionUID的作用。

序列化与反序列化

含义

  • 序列化:将java对象转化为字节序列。
  • 反序列化:将字节序列转化为java对象。

序列化两大用途:

  1. 存储:将java对象序列化成字节码保存到磁盘或者Redis等,需要的时候反序列化成java对象
  2. RPC:将java对象序列化成字节码在网络上传输

serialVersionUID

序列化时把serialVersionUID 写入文件中,反序列化时检测文件中的serialVersionUID 和类的serialVersionUID 是否一样。如果一样可以则可以反序列化,否则会抛异常,反序列化会失败。

如果没有指定serialVersionUID,那么对象在被序列化的时候,JVM会根据包名、类名、变量、参数、返回值等自动生成serialVersionUID,如果我们修改了对象的成员,那么这个serialVersionUID就会发生变化。当对象被反序列化的时候,这两个值不相等,就会报错。

所以需要手动指定serialVersionUID:

  1. private static final long serialVersionUID = 1L;

实例

例1:正常用法

Entity

  1. package com.knife.entity;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. @Data
  5. public class User implements Serializable {
  6. private static final long serialVersionUID = 333225L;
  7. private Long id;
  8. private String userName;
  9. }

Controller

  1. package com.knife.controller;
  2. import com.knife.entity.User;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.RestController;
  5. import java.io.*;
  6. @RestController
  7. public class TestController {
  8. @GetMapping("serialize")
  9. public String serialize() {
  10. User user = new User();
  11. user.setId(2L);
  12. user.setUserName("Tony");
  13. try {
  14. FileOutputStream fos = new FileOutputStream("User.txt");
  15. ObjectOutputStream oos = new ObjectOutputStream(fos);
  16. oos.writeObject(user);
  17. oos.flush();
  18. oos.close();
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. return e.getMessage();
  22. }
  23. return "serialize success";
  24. }
  25. @GetMapping("deSerialize")
  26. public String deSerialize() {
  27. User user;
  28. try {
  29. FileInputStream fis = new FileInputStream("User.txt");
  30. ObjectInputStream ois = new ObjectInputStream(fis);
  31. user = (User) ois.readObject();
  32. ois.close();
  33. System.out.println(user.toString());
  34. } catch (IOException | ClassNotFoundException e) {
  35. e.printStackTrace();
  36. return e.getMessage();
  37. }
  38. return "deSerialize success";
  39. }
  40. }

测试

1.序列化

b2c1d101dead447dbb9dac5998203b24.png

此时后端生成了User.txt

6bbc1421da644a0599938a847d1c8a0d.png

2.反序列化

b2e1a9bf1a6842a6817bac0263e7b594.png

后端输出

  1. User(id=2, userName=Tony)

例2:未指定serialVersionUID时报错

Entity中去掉serialVersionUID,序列化,然后修改Entity,添加一个字段,然后反序列化,此时会报错。

Entity中去掉serialVersionUID,如下:

  1. package com.knife.entity;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. @Data
  5. public class User implements Serializable {
  6. private Long id;
  7. private String userName;
  8. }
  1. 序列化

5482d146c81349d884457f91a80abc39.png

此时生成User.txt

32bf7a8e94ae4af4930509289aa961ba.png

2.增加字段并重启应用

Entity添加一个字段

  1. package com.knife.entity;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. @Data
  5. public class User implements Serializable {
  6. private Long id;
  7. private String userName;
  8. private String age;
  9. }

重启应用

3.反序列化

d194529d28d944c0913d43b853c6ca29.png

可以发现,反序列化报错。原因是:本地类不兼容:流的serialVersionUID = 3441701338525863619,本地类的serialVersionUID = 2482712775234331218

发表评论

表情:
评论列表 (有 0 条评论,255人围观)

还没有评论,来说两句吧...

相关阅读