20200715——关于序列化问题 Serializable

在修改公司项目的时候遇到这个问题,联想起之前做一篇博客。代码红线不贴了。

序列化的概念

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

序列化的方式

把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;(持久化对象)
在网络上传送对象的字节序列。(网络传输对象)

如何实现序列化

实现两个接口

Serializable 接口
Externalizable 接口

Serializable接口

一个对象想要被序列化,那么它的类就要实现此接口或者它的子接口。
这个对象的所有属性(包括private属性、包括其引用的对象)都可以被序列化和反序列化来保存、传递。
不想序列化的字段可以使用transient修饰。
由于Serializable对象完全以它存储的二进制位为基础来构造,因此并不会调用任何构造函数,因此Serializable类无需默认构造函数,但是当Serializable类的父类没有实现Serializable接口时,反序列化过程会调用父类的默认构造函数,因此该父类必需有默认构造函数,否则会抛异常

使用transient关键字阻止序列化虽然简单方便,但被它修饰的属性被完全隔离在序列化机制之外,导致了在反序列化时无法获取该属性的值,而通过在需要序列化的对象的Java类里加入writeObject()方法与readObject()方法可以控制如何序列化各属性,甚至完全不序列化某些属性或者加密序列化某些属性。

Externalizable 接口

它是Serializable接口的子类,用户要实现的writeExternal()和readExternal() 方法,用来决定如何序列化和反序列化。

因为序列化和反序列化方法需要自己实现,因此可以指定序列化哪些属性,而transient在这里无效

对Externalizable对象反序列化时,会先调用类的无参构造方法,这是有别于默认反序列方式的。如果把类的不带参数的构造方法删除,或者把该构造方法的访问权限设置为private、默认或protected级别,会抛出java.io.InvalidException: no valid constructor异常,因此Externalizable对象必须有默认构造函数,而且必需是public的。

serialVersionUID

serialVersionUID字段用来控制序列化的版本

一个对象数据,在反序列化过程中,如果序列化串中的serialVersionUID与当前对象值不同,则反序列化失败,否则成功。

如果serialVersionUID没有显式生成,系统就会自动生成一个。生成的输入有:类名、类及其属性修饰符、接口及接口顺序、属性、静态初始化、构造器。任何一项的改变都会导致serialVersionUID变化。

属性的变化都会导致自动生成的serialVersionUID发生变化。例如,对于对象A,我们生成序列化的S(A),然后修改A的属性,则此时A的serialVersionUID发生变化。反序列化时,S(A)与A的serialVersionUID不同,无法反序列化。会报序列号版本不一致的错误。

实现代码

这个从网上找的
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值