文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

private static final Long serialVersionUID= 1L详解

2023-09-11 11:46

关注

我们知道在对数据进行传输时,需要将其进行序列化,在Java中实现序列化的方式也很简单,可以直接通过实现Serializable接口。但是我们经常也会看到下面接这一行代码,

private static final Long serialVersionUID= 1L;

这段代码到底有什么用呢? 为什么有些代码写了它,有些代码没写?

首先我们看这一段代码

public class Person implements Serializable {    private String name;    private Integer age;    public Person(){}    public Person(String name, Integer age){        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    @Override    public String toString() {        return "Person{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }}
public class IOTest {    public static void main(String[] args) throws IOException, ClassNotFoundException {        out();        //in();    }    public static void out() throws IOException {        ObjectOutputStream oos = new ObjectOutputStream(                new FileOutputStream("C:\\Users\\Lenovo\\Desktop\\java练习\\src\\main\\resources\\Person.txt"));        Person person = new Person("张三",18);        oos.writeObject(person);        oos.close();    }    public static void in() throws IOException, ClassNotFoundException {        ObjectInputStream ois = new ObjectInputStream(                new FileInputStream("C:\\Users\\Lenovo\\Desktop\\java练习\\src\\main\\resources\\Person.txt")        );        Object object = ois.readObject();        System.out.println(object);    }}

执行该段代码,运行结果

然后将out();注释掉, 执行in();

如果这个时候我修改了Person类,增加sex成员变量

public class Person implements Serializable {    private String name;    private Integer age;        private char sex;    public Person(){}    public Person(String name, Integer age, char sex) {        this.name = name;        this.age = age;        this.sex = sex;    }    public char getSex() {        return sex;    }    public void setSex(char sex) {        this.sex = sex;    }    public Person(String name, Integer age){        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    @Override    public String toString() {        return "Person{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }}

我在执行IOTest类中的in()方法(注释掉out();方法), ,发现会报错

这是为什么呢?为什么只是在Person类中增加了一个char sex成员变量, 执行in()方法就会报错.

如果在以上Person类中添加

private static final long serialVersionUID = 1L;

按照案例代码1中的执行顺序运行一遍代码,(先将Person.txt文件中的内容全部删除)

这是为什么呢?

这里先搞清楚java中的序列化和反序列化代表什么意思

序列化:把Java对象转换为字节序列的过程

方序列化:把字节序列恢复为Java对象的过程。

这里看一下案例代码1执行所产生的的错误:invalidClassException,然后我们再看下面一行serialVersionUID有两个不同的值,仔细分析,发现这两个不同的值才是产生异常的原因。

在案例1代码中我们在Person类中没有设置serialVersionUID值。我们首先执行的是out()方法,作用就是将person对象写入(序列化)到Person.txt文件中,而在序列化的过程中Person类也会产生一个serialVersionUID值,如果Person类中没有定义serialVersionUID值,则系统会自动生成一个值,就是第一个5428155211170925772,会存入到Person.txt文件中,然后我们在Person类中增加了一个sex成员变量,注释掉out()方法,执行in()方法,相当于一个反序列化的过程,这个时候会报错,是因为在Person类由于被增加了一个sex成员变量,导致系统生成的serialVersionUID改变了,变成了-1544469845932994986,而我们存入到Person.txt文件中的person对象的serialVersionUID却是5428155211170925772所以系统就判定这两个Person类不是同一个,就会导致invalidClassException异常。

案例2代码中我们规定了Person类中private static final long serialVersionUID = 1L的值,这就保证了无论Person类再怎么变,serialVersionUID都是一个固定的值,不再是系统生成的,这就能够避免Person类增加或者减少成员变量都不会导致serialVersionUID改变。

这是java源码中的一段话

如果可序列化类没有显式声明serialVersionUID,那么序列化运行时将根据类的各个方面计算该类的默认serialversion UID值,如Java对象序列化规范中所述。此规范将枚举类型的seriaVersionUID定义为0L。但是。强烈建议除枚举类型之外的所有可序列化类都显式声明serialVersionUID值,因为默认的

seriaverslon UID计算对类细节非常敏感,这些细节可能因编译器实现而有所不同。因此在反序列化过程中可能会导致意外的InvalidClassException。因此。为了保证不同java编译器实现中的serialVerslonUID值一致。可序列化类必须声明显式serialVersionUID值。此外。强烈建议显式serialVersionUID声明尽可能使用私有修饰符。因为此类声明仅适用于立即声明的类—serialVersionUID字段作为继承成员没有用处。数组类不能声明显式的serialversionUID,因此它们总是具有默认的计算值,但数组类不需要匹配serialVersion UID值。

来源地址:https://blog.csdn.net/m0_50370837/article/details/129017300

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯