序列化和反序列化

1,899 阅读3分钟

序列化隐秘的吭,你踩过了没?

序列化和反序列化

Java序列化的目的主要有2个:

  • 网络传输
  • 对象持久化

image-20230301144505527

当2个相对独立的进程,需要进行跨进程服务调用时,就需要把被传输的Java对象编码为字节数组或者ByteBuffer对象

接收方只需要把这些字节数组或者Bytebuf对象重新解码成内存对象即可实现通信、调用的作用。

image-20230301145117301

那么在我们使用序列化的时候有哪些需要注意的,避免的坑呢?

成员变量不能以is开头

阿里的《Java开发手册》明文规定了:成员变量禁止使用类似 isXxxx 的命名方式,也不要有isXxx命名的方法

image-20230301150018030

image-20230301145401694

大概的意思就是:不要加is前缀,因为部分框架序列化的时候,会以为对应的字段名是isXxxx后面的Xxxx

  • 比如:isSucceed序列化成Succeed,前端读取isSucceed的时候就会发现没有这个字段,然后出错了。

u=4214115302,3196714167&fm=253&fmt=auto&app=120&f=JPEG

这里面的序列化框架其实就是fastjson,我们可以直接去看他的源码

fastjson源码分析:computeGetters

去找get前缀的方法,然后进行字符串切割找到get后面的

image-20230301161434898

去找is前缀的方法,然后进行字符串切割

image-20230301161413220

  • 这里还进行了驼峰命名的判断:ixXxx,第三个字符是否是大写等判断

所以isSucceed字段会被fastjson框架认为Succeed字段。

image.png

默认值

成员变量的默认值同样会带来坑

同样是阿里的《Java开发手册》里面也是规定了:POJO类、RPC方法必须使用包装类型

image.png

关于包装类型和基本类型的区别,如果还有不清楚的,赶紧去看,这是最基础的面试知识点..

POJO类必须使用包装类型

尽量让错误暴露在编译期,不要拖到运行期

基本类型具有初始值,比如:

  • Int:0
  • float:0.0f
  • boolean:false

一个统计点赞的接口里面的返回值包含一个表示点赞数变化的字段,当发生错误的时候,这个字段没有进行赋初始值,就会出现以下情况:

  • 基本类型:读默认值,0,表达的意思就是没有点赞数变化,程序上并不知道是服务器那边出了错。
  • 包装类型:读到了个null,程序上是知道服务器那边出错了,可以进行对应的显示,比如显示 - ,表示读取不到等操作。

u=3180711090,4079282331&fm=253&fmt=auto&app=138&f=JPEG

总的来说就是:如果字段设置为基础类型并且基础类型的默认值具有业务意义,那么就会出错,并且无法感知错误

RPC方法的返回值和参数必须使用包装类型

RPC调用常常具有超时导致调用失败的情况

如果用包装类型,那么在接收方,就能感知到,这次RPC调用是成功,还是失败。

包装数据类型的null值具有表示额外的信息功能

彦祖来都来了,点个赞👍再走吧,这对我来说真的非常重要