java 序列化 详细介绍

01:要保存一个对象的二进制形式, 到二进制文件中,那么这个对象就必须实现序列化, 必须继承Serializable接口。

02:实现接口的目的是 让java虚拟机 根据这个类的 各个内容 生成 一个 序列号。

03:在开发过程中,经常会 一个类的内容反复的修饰,导致虚拟机 生成的序列号 会发生改变, 如果是这样的话,那么在反序列化过程中,就会报异常,找不到之前的类的 二进制文件。所以强烈建议:
在当前的类, 包括这个类的父类中,都显示的写上 序列号,序列号的写法是:
修饰符 static final serialVersionUID = xxxxxL;
修饰符可以自己定义 , 后面的值必须加上L

04:Serializable接口 是一个 标记接口 , 并没有要实现的方法, 它的目的是产生一个序列号。

05:关于保存重复对象的 序列化 机制。
在这里插入图片描述
在这里插入图片描述

06:在反序列化的过程中,也就是说 将文件中的 被序列化的对象 读取到 内存的过程。注意:
将文件中的数据读取到 内存中之后 , 会将对象还原, 并且在内存中 分配空间 和一个地址符 , 这个地址符会被引用。

07:如果一个类implements了一个序列化接口 , 表示这个类是可序列化。此时要注意。
01:这个类中的所有的 数据域 都必须是可序列化的 , 否则当前类还是无法实现序列化。
如果序列化一个集合 或者数组, 那么每个元素 都必须 是可序列化的,单独一个不可序列化的元素都会导 致序列化失败,虽然集合接口不是可序列化的,但是 具体的集合类都是可序列化的。

02:或者有一些比较 烦恼的引用对象 我们无法实现序列化,或者不想实现序列化,那么我们可以 使用transient修饰符去修饰, 那么在序列化过程中会 跳过 这个数据域。
解释transient修饰的变量 和 其他情况:
1:一个被 transient修饰的数据域无法被序列化, 那么在反序列化的时候,这个属性 会被赋值为系统默认值(0 , false ,null),即便是之前被 java虚拟机初始化过了,有确切的值, 或者在后面的使用过程中 一次又一次的被修改和赋值 ,但是反序列化的过程中 , 直接 赋值系统默认值。
2:如果在反序列化的过程中 , 我们在之前的类中 又 添加了很多数据域(序列化的时候并没有这些数据域),那么在反序列化的时候,我们不管 被添加的数据域是否 又初始值, 还是其他的杂七杂八的情况, 直接赋值系统默认值(false , null , 0)。
3:如果 我们将类中的一些数据域 删掉了一部分(序列化的时候有这些数据域),那么反序列化的时候 ,由于子.class文件中找不到 这些已经被删掉的数据域, 则就会舍弃掉。
4:如果两部分数据域之间 名字匹配 而类型 不匹配,那么对象输入流不会尝试 将一种 类型 转换 成另一种类型,因为这两个对象不兼容, 且会报错,此时建议将这个属性要么删掉,要么还原为之前的类型。

03:这个类的父类 如果没有实现序列化,那么这个父类必须 有 无参的构造方法。否则回复数据的时候会报错。

08:序列化一个当前对象的时候,仅仅会序列化 跟对象有关系的数据域,而静态数据域不会参与序列化。

09:如果子类实现了序列化,但是父类并没有实现序列化,那么此时父类一定要有一个 无参的构造方法(方法体不做要求),它的作用是在子类在反序列化还原为对象的时候 , 方便调用 这个父类的 无参的构造方法,将父类的数据域初始化。
在序列化这样的子类的时候,要注意了, 我们仅仅序列化,定义在子类中的数据域(跟子类有关系的数据域),定义在父类中的数据域我们不会序列化保存。 但是在反序列化的时候,会调用父类的无参的构造函数, 初始化 父类中的数据域(切记,这里并不是初始化为默认值,而是初始化为 声明变量, 或者构造函数中赋的值。说白了,就是要调用父类的构造方法 , 重新构造以下父类)。 如果父类还有父类,那么沿着继承链,一直走下去。

10:如果父类实现了 序列化接口 , 那么子类也默认实现了这个接口,但是建议 都明确的写上序列化接口,且都在自己的类中写上序列号。

11:如果在一个实现了序列化的类中, 有一个我们认为很烦人的 引用对象没办法对他进行序列化,但是要保证这个子类 可以被序列化,此时我们需要做的就是 将这个数据域 使用transient修饰以下,序列化的时候跳过去,不去保存这个数据域。
但是我们 在反序列化 恢复 这个对象的时候 , 这个使用transient修饰的 引用对象 赋值时null。我们有不想看到这个null值。
可以使用 java给我们提供的后门方法, 在序列化的时候,捎上跟这个引用有关联的数据, 在反序列化的时候,我们在这个后门方法中,明确的 使用new 创建一个对象,并且赋值给 这个反序列化的对象 就可以了。
代码如下:
在这里插入图片描述
在这里插入图片描述

关键点:
01:在 当前序列化类中 写一对儿 这么个方法, 且签名必须时一摸一样的,不可以被改变。
private void writeObject(ObjectOutputStream os){
//默认被序列化 的内容
os.defaultWriteObject();
//以下是顺便捎带 需要被序列化的内容
os.writeXXX();
}
private void readObject(ObjectInputStream is){
//默认被反序列化 的内容
is.defaultReadObject();
//读取被捎带序列化的内容 , 然后使用他 构造对象 , 且赋值给当前类 的 数据域引用变量。
Xxx yyy = New xxx( is.readXXX() );
}

///需要弥补的东西 内部接口!!!!!! 以下是问题: 需要 总结 在总结 敲代码 在敲代码!!!
01:在类中定义接口的情况!!! 这个需要 彻底把定义概念弄清楚!!

请关注:计算机软件技术

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

15737443266

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值