面试题:实现 Serializable 接口就算了, 为什么还要显示指定 serialVersionUID 的值? static 属性为什么不会被序列化?

实现序列化和反序列化为什么要实现 Serializable 接口?

在Java中,要实现对象的序列化和反序列化,需要让该类实现Serializable接口,主要原因和机制如下:

  1. 标识作用Serializable接口实际上是一个标志接口(Marker Interface),这意味着它不包含任何方法。当一个类实现了Serializable接口,就是在向Java序列化机制表明:“这个类的对象是可以被序列化的”。这是Java序列化机制识别可序列化类的一个标准。

  2. 默认序列化机制:通过实现Serializable接口,Java的序列化机制会自动采用默认的序列化规则来处理该类的实例。这意味着,除非特别标注(如使用transient关键字标记不需要序列化的成员变量),否则类中的所有实例变量(包括基本类型和实现了Serializable的引用类型)都将被序列化。

  3. 版本控制:序列化机制允许通过serialVersionUID字段来控制类的版本兼容性。尽管这个字段不强制要求在实现Serializable接口时提供,但建议显式定义,以确保类在进化过程中(如添加、删除字段)的序列化兼容性。

  4. 安全性考量:序列化操作涉及对象状态的读取和写入,可能引发安全风险,如敏感数据泄露或对象注入攻击。实现Serializable接口意味着开发人员需要考虑这些安全因素,并可能需要采取额外的安全措施。

总之,实现Serializable接口是Java中启用对象序列化和反序列化功能的标准化方式,它不仅标示了类的序列化能力,还允许Java虚拟机自动处理对象的序列化细节,同时也提醒开发者注意版本控制和安全性问题。

实现 Serializable 接口就算了, 为什么还要显示指定 serialVersionUID 的值?

如果不显示指定 serialVersionUID, JVM 在序列化时会根据属性自动生成一个 serialVersionUID, 然后与属性一起序列化, 再进行持久化或网络传输. 在反序列化时, JVM 会再根据属性自动生成一个新版 serialVersionUID, 然后将这个新版 serialVersionUID 与序列化时生成的旧版 serialVersionUID 进行比较, 如果相同则反序列化成功, 否则报错.

如果显示指定了 serialVersionUID, JVM 在序列化和反序列化时仍然都会生成一个 serialVersionUID, 但值为我们显示指定的值, 这样在反序列化时新旧版本的 serialVersionUID 就一致了.

在实际开发中, 不显示指定 serialVersionUID 的情况会导致什么问题? 如果我们的类写完后不再修改, 那当然不会有问题, 但这在实际开发中是不可能的, 我们的类会不断迭代, 一旦类被修改了, 那旧对象反序列化就会报错. 所以在实际开发中, 我们都会显示指定一个 serialVersionUID, 值是多少无所谓, 只要不变就行.

static 属性为什么不会被序列化?

因为序列化是针对对象而言的, 而 static 属性优先于对象存在, 随着类的加载而加载, 所以不会被序列化.

看到这个结论, 是不是有人会问, serialVersionUID 也被 static 修饰, 为什么 serialVersionUID 会被序列化? 其实 serialVersionUID 属性并没有被序列化, JVM 在序列化对象时会自动生成一个 seri 属性值赋给自动生成的 serialVersionUID.alVersionUID, 然后将我们显示指定的 serialVersionUID

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值