每日解惑:private static final long serialVersionUID = 1L
我们在项目开发的时候常常看到一个实体类一开始就有这么一行代码
private static final long serialVersionUID = 1L
我们不免产生以下的疑问:
这么写是什么意思呢?为什么要这么写?有些类又为什么没有
一、serialVersionUID 是什么?
serialVersionUID 相当于java类的身份证。主要用于版本控制。
serialVersionUID作用是序列化时保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。
有两种生成方式:
一个是默认的1L,比如:private static final long serialVersionUID = 1L;
一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;
二、为什么要有serialVersionUID?
1.什么是序列化和反序列化
- 序列化是一种用来处理对象流的机制
- 对象的序列化就是为了数据传输,在你的代码的里是对象格式,而在传输的时候不可能还保持对象的样子。当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列,也就是流的形式在网络上传送。发送方需要把这个Java对象转换为流,才能在网络上传送;接收方则需要把流再恢复为Java对象;
- 我们在分布式应用中,难免会通过网络传输各种类型的数据,其中就包括Java对象,我们需要其统一转化成二进制流,传输过去后再从二进制流还原成对象,供请求方进行读写操作;
- 而这个对象转化成流的过程,我们称为序列化; 流转换成对象的过程,就是反序列化
2.为什么要实现序列化
- 将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本
- 将对象从一个应用程序域发送至另一个应用程序域。实现serializabel接口的作用是就是可以把对象存到字节流,然后可以恢复,而网络传输的基础则是字节流,故既可以远程传输,又可以本地化恢复。(Ps:不实现序列化接口得话,服务器并不能识别其为对象类型,这是关键)
3.如何实现序列化
序列化和反序列化的前提就是类实现Serializable接口(标记接口),implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象;接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流
作用是什么
- Java的序列化机制是通过运行时判断类的序列化ID(serialVersionUID)来判定版本的一致性
- 在反序列化时,java虚拟机会通过二进制流中的serialVersionUID与本地的对应的实体类进行比较,如果相同就认为是一致的,可以进行反序列化,正确获得信息,否则抛出序列化版本不一致的异常
三、什么时候才需要序列化?
- 当你想用套接字在网络上传送对象的时候;
- 当你想把的内存中的对象写入到硬盘的时候;
- 当你想通过RMI传输对象的时候;(远程调用方法,如RPC)
涉及到数据传输或者存储的类,严格意义上来说都要加上序列化ID,这也是一种良好的编程习惯