ceacer 2 已发布 1月29号 分享 已发布 1月29号 相信不少人在Java的类文件里见过private static final long serialVersionUID = 1L; ,但是很多人却不清楚这个字段的用处,那这个字段到底有什么用呢? 在谈这个字段的作用前,我们先来聊一聊Java中对象的序列化。 Table of Contents 什么是对象序列化? 序列化:把对象转化为可传输的字节序列过程称为序列化。 反序列化:把字节序列还原为对象的过程称为反序列化。 对象序列化有什么作用? 假如服务端与客户端进行通信,然后服务端想要把一个对象的数据返回给客户端,在网络IO只能传输字节的情况下,客户端怎样才能接受到这个对象的正确数据呢?答案是序列化,将对象序列化后再进行传输,假如没有序列化,直接将对象转成字节数组直接传输,那么客户端收到数据后就无法正确地将数据还原成对象。 而序列化就是一种规则,就是一种可以让对象按照一定的规则转成字节数组,而使得字节数组能够在进行网络传输或者跨平台存储后能够将字节数据反序列化还原回正确的对象。 目前对象序列化最常见的方式有JSON、XML、Hessian等,还有Java语言原生的序列化方式Serializable。 JSON序列化和Serializable区别 JSON JSON 是一种轻量级的数据交换格式。 JSON 序列化就是将数据对象转换为 JSON 字符串。在序列化过程中抛弃了类型信息,所以反序列化时只有提供类型信息才能准确地反序列化。相比于其他的序列化方式,JSON 可读性和兼容性比较好,较为方便调试,但此方式常常成为黑客的攻击点,攻击者巧妙地利用反序列化过程构造恶意代码,使得程序在反序列化的过程中执行任意代码,比如最近业内传出FastJson漏洞 ,就是利用了此方式的序列化/反序列化导致的。 Serializable Serializable是Java语言特有的序列化方式,它是一个序列化接口,java类可以通过实现Serializable接口来实现该类对象的序列化,这个接口非常特殊,没有任何方法,只起标识作用,Java序列化保留了对象类的元数据(如类、成员变量、继承类信息等),以及对象数据等,兼容性最好,但不支持跨语言,而且性能一般。 serialVersionUID作用 serialVersionUID其实是Java原生的Serializable序列化中的一个功能,其最本质的作用是记录一个对象的版本号,使得对象能够兼容同一个版本号的不同特性。如果实现了Serializable接口的类没有显示定义serialVersionUID,那么JDK编译时会根据属性隐式生成一个对应的serialVersionUID,当这个类发生属性修改变动时,其隐式的serialVersionUID会对应发生改变,所以当实现Serializable接口的类,建议显示地声明serialVersionUID字段定义版本号,使得对象序列化兼容性更好。下面以代码为例看看serialVersionUID是如何在对象的序列化和反序列化中发挥兼容作用的! 不声明serialVersionUID 我们定义一个Student类先定义name和age两个属性,并实现Serializable接口,不显示声明serialVersionUID字段,然后通过序列化创建一个对象保存到F盘下的一个temp.txt文件中: 运行上图代码在F盘下生成了一个temp.txt文件,里面保存有一个name为小明,age为18的Student对象。 然后我们先在Student里再加个sex属性,再将上面代码保存的在temp.txt里面的对象数据反序列化成对象: 运行添加sex属性后的反序列化代码,发现直接抛出了异常java.io.InvalidClassException,并明显提示到serialVersionUID版本号不一致: 显示声明serialVersionUID我们再显示声明serialVersionUID字段后,并定义一个版本号后,再将上面的代码流程跑一遍: 代码运行成功,成功地从F盘下的temp.txt文件中的对象反序列化成对象,并且没有出现不声明serialVersionUID字段时抛出的InvalidClassException异常。 serialVersionUID这个字段就是用来定义某个对象文件的版本号,同版本号时才能序列化/反序列化成功,无论是否对类属性进行了增删改,也会成功!反之,假如版本号不一致,哪怕属性完全一致,也会抛出异常,反序列化失败! 总结 serialVersionUID主使Java的Serializable接口的序列化/反序列化兼容问题,如果你的类实现的Serializable接口,建议一定要加上serialVersionUID这个字段显示声明版本号,要不然在一些接口调用或者RPC传输时,假如你哪天给这个类增加某个属性,使得隐式的serialVersionUID版本号不一致了,并且这个功能之前在某个阴暗的小角落还保存着序列化的对象时,哪天线上直接爆出反序列化异常失败了,你的领导肯定会口吐芬芳地夸赞你一番。 评论链接 在其他网站上分享 更多分享选项...
推荐帖
创建账户或登录以发表评论
您需要成为会员才能发表评论
创建一个帐户
在我们的社区注册一个新账户。很简单!
注册新账户登入
已有账户?在此登录
立即登录