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

2021-03-01 19:29

阅读:543

标签:关键字   转换   产生   需要   否则   必须   图片   执行   实例   

 

阿里的开发手册中有下面这条强制性的规定,默认在序列化类中必须含有serialVersionUID,请不要修改 serialVersionUID 字段,避免反序列失败;看到这里可能脑海里就会出现一系列的问题。

技术图片

  • 序列化和反序列化是什么?
  • 实现序列化和反序列化为什么要实现 Serializable 接口?
  • 实现 Serializable 接口就算了, 为什么还要显示指定 serialVersionUID 的值?
  • 我要为 serialVersionUID 指定个什么值?

一、序列化和反序列化

  • 序列化:把对象转换成字节序列的过程称之为对象的序列化。
  • 反序列化:把字节序列恢复为对象的过程称之为反序列化。

二、什么时候需要用到序列化和反序列化呢?

当我们只在本地JVM中运行Java实例,这个时候我们是不需要进行序列化与反序列化的,但是当我们需要将内存中的对象持久化到磁盘或者数据库中的时候,当我们需要与浏览器进行交互的时候,当我们需要实现RPC(远程调用),这个时候我们就需要进行序列化与反序列化。

三、为什么要实现 Serializable 接口?

在 Java 中实现了 Serializable 接口后, JVM 会在底层帮我们实现序列化和反序列化, 如果我们不实现 Serializable 接口, 那自己去实现一套序列化和反序列化。

四、为什么还要指定serialVersionUID的值?

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

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

具体示例;

技术图片

 技术图片

先后执行测试类中的序列化代码   , 然后 User 类新增一个属性 sex ,  执行反序列化的代码结果如下:

技术图片

 报错结果为序列化与反序列化产生的 serialVersionUID 不一致.

如果我们显示的指定serialVersionUID  (private static final long serialVersionUID = 1L;) ,那么就不会问题。

结果如下:

技术图片

五、Java 序列化的其他特性

被 transient 关键字修饰的属性不会被序列化, static 属性也不会被序列化。

技术图片

技术图片

 先后进行序列化与反序列化的代码测试结果如下:

 技术图片

 技术图片

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

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

看到这个结论, 是不是有人会问, serialVersionUID 也被 static 修饰, 为什么 serialVersionUID 会被序列化? 

其实 serialVersionUID 属性并没有被序列化, JVM 在序列化对象时会自动生成一个 serialVersionUID, 然后将我们显示指定的 serialVersionUID 属性值赋给自动生成的 serialVersionUID。

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

标签:关键字   转换   产生   需要   否则   必须   图片   执行   实例   

原文地址:https://www.cnblogs.com/dongl961230/p/14426497.html


评论


亲,登录后才可以留言!