序列话ID的作用
1、序列化ID的作用
其实,这个序列化ID起着关键的作用,它决定着是否能够成功反序列化!简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。等会我们可以通过代码验证一下。
2、序列化ID如何产生
当我们一个实体类中没有显示的定义一个名为“serialVersionUID”、类型为long的变量时,Java序列化机制会根据编译时的class自动生成一个serialVersionUID作为序列化版本比较,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID。譬如,当我们编写一个类时,随着时间的推移,我们因为需求改动,需要在本地类中添加其他的字段,这个时候再反序列化时便会出现serialVersionUID不一致,导致反序列化失败。那么如何解决呢?便是在本地类中添加一个“serialVersionUID”变量,值保持不变,便可以进行序列化和反序列化。
3、验证“serialVersionUID”不一致导致反序列化失败
public class Person implements Serializable { //序列化ID //private static final long serialVersionUID = -5809782578272943999L; private int id; private String name; //private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // public int getAge() { // return age; // } // // public void setAge(int age) { // this.age = age; // } // @Override // public String toString() { // return "Person{" + // "id=" + id + // ", name='" + name + '\'' + // ", age=" + age + // '}'; // } }
复制上文的序列化与反序列化代码
@Test /** * 对象序列化 */ public void test5(){ Person person = new Person(); person.setId(1); // person.setAge(12); person.setName("小明"); ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(new FileOutputStream("d:/io/data.txt")); oos.writeObject(person); System.out.println("序列化成功"); } catch (IOException e) { e.printStackTrace(); } finally { try { if(oos != null) { oos.close(); } } catch (IOException e) { e.printStackTrace(); } } }
运行一下,会在控制台中打印“序列化成功。”,然后我们在Person类中再添加一个字段,name,然后直接从data.txt中反序列化,再运行一下,看看会出现什么问题。
@Test /** * 对象反序列化 */ public void test6(){ Person person = null; ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream("d:/io/data.txt")); person = (Person) ois.readObject(); System.out.println(person); System.out.println("反序列化成功"); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { try { if(ois != null){ ois.close(); } } catch (IOException e) { e.printStackTrace(); } } }
运行一下,不出意外,报了一个异常。
总结:
虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)。
原文链接:https://blog.csdn.net/qq_51409098/article/details/126412452
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端