java基础--19Java序列化(Serializable)

目录

1.何为序列化,为什么需要序列化

2.序列化的方式

3.自定义序列化

4.版本管理:


1.何为序列化,为什么需要序列化

      如果我们将对象保存到磁盘或者进行网络传输,必须将这个对象进行序列化,即实现Serializable接口,如果不进行序列化,那么保存对象到磁盘的时候会报错,即磁盘IO操作对象的时候会报错:

   说到底就是对象的格式不正确,必须通过序列化将对象的格式转换为特殊的格式才能在磁盘上面存储该对象,准确的说就是要转换成字节,转化成可以用磁盘进行存储的格式。

 什么似乎要用到序列化:

实际开发中有哪些用到序列化和反序列化的场景?

  1. 对象在进行网络传输(比如远程方法调用 RPC 的时候)之前需要先被序列化,接收到序列化的对象之后需要再进行反序列化;
  2. 将对象存储到文件中的时候需要进行序列化,将对象从文件中读取出来需要进行反序列化。
  3. 将对象存储到缓存数据库(如 Redis)时需要用到序列化,将对象从缓存数据库中读取出来需要反序列化。

序列化协议对应于 TCP/IP 4 层模型的哪一层?

2.序列化的方式

  •     JDK自带 只需实现 java.io.Serializable接口即可。
  •    JSON格式 

  •    Google ProtoBuf

  •    Kryo 是一个高性能的序列化/反序列化工具

  •   hessian 是一个轻量级的,自定义描述的二进制 RPC 协议。hessian 是一个比较老的序列化实现了

  这几种序列化的方式进行比较:Java中序列化的集中方式比较(json,serialize,protobuf) | 噢~哟~哟——每天进步一点点o-u-u

  

    序列化的方式就是实现Serializable接口就行了,在进行序列化操作时,会判断要被序列化的类是否是Enum、Array和Serializable类型,如果都不是则直接抛出NotSerializableException。

3.自定义序列化

   自定义序列化的方式其实就是我们希望对象的某些属性不被序列化,要实现这种效果有三种办法:

    关键字:transient

     某些数据域是不可以被序列化的,这些域如果处理不当还可能会引起本地方法崩溃,java 拥有一种很简单的机制来防止这种域被序列化,就是transient关键字来修饰这个域。还有就是静态的域,静态成员属于类级别的,所以不能序列化,序列化只是序列化了对象而已。

  添加writeObject和readObject方法

   Java调用ObjectOutputStream类检查其是否有私有的,无返回值的writeObject方法,如果有,其会委托该方法进行对象序列化。

  使用Externalizable实现

  使用Externalizable接口需要实现writeExternal以及readExternal方法~在writeExternal方法中,写入想要外部序列化的元素

4.版本管理:

    当存储一个对象的时候,这个对象所属的类也必须进行存储,其中这个类比较重要的描述是序列化的版本唯一的ID,他是数据域类型和方法签名的指纹,是用来做版本控制的,

  serialVersionUID,之前说过他是一个指纹,序列化系统可以读入这个类的对象的不同版本,如果只是方法发生了变化,那么在读入新的对象数据时不会有什么问题,如果数据域发生了变化,那么就可能出问题,比如新的类增加了数据域,这种情况下对象输入流将会尽力的将流对象转换成这个类当前的版本,对象输入流会去比较非瞬时和非静态的数据域,进行一一转换,如果类型不一致,对象输入流不会做类型的转换,因为这两个对象不兼容。 如果序列化存储了一个对象,然后修改了他的serialVersionUID,再反序列化回来是要失败的。

 《阿里巴巴Java开发手册》中规定,在兼容性升级中,在修改类的时候,不要修改serialVersionUID的原因。除非是完全不兼容的两个版本。所以,serialVersionUID其实是验证版本一致性的。

  一旦类实现了Serializable,就建议明确的定义一个serialVersionUID。不然在修改类的时候,就会发生异常。因为系统会默认添加serialVersionUID,序列和反序列的会不一样,导致异常的产生。

 既然是验证版本一致性的,在做版本升级的时候(非兼容性升级),记得要修改这个字段的值哦,这样可以避免序列化混乱。

       现在需要将一个对象返回给前端,那么该对象是否需要实现 Serializable接口,并提供一个默认的serialVersionUID?如果不实现会有什么影响?一般来说如果你的对象需要网络传输或者持久化(对象直接转换为字节的形式传输),那么就需要实现Serializable接口。如果只是转换为字符串的形式与网络打交道,那么就不需要实现Serializable接口。

参考文章:

你的JavaBean是否真的需要实现Serializable - 云+社区 - 腾讯云

讲真,下次打死我也不敢随便改serialVersionUID了

Serializable和Externalizable浅析 - 王孟君的个人空间 - OSCHINA - 中文开源技术交流社区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

时空恋旅人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值