序列话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

posted @ 2023-04-13 16:51  YE-  阅读(78)  评论(0编辑  收藏  举报