关于 Java 中实现 Serializable 争议
在 Java 中有一个特殊的接口 Serializable
,很长一段时间只知道其与类的序列化和反序列化有关,有的人习惯给实体类实现这个方法并定义一个常量 serialVersionUID 有些人在编码过程中从来不使用 Serializable
. 这两种截然不同的做法,都不曾听说有哪一种会遇到什么问题,然而这本身就是一种令人困扰的话题,究竟要不要去实现 Serializable
?
关于这个问题,最早是在 V 站看过一篇讨论,同意需要实现的占相对多数,也有不少人认为完全不需要去实现 Serializable.
首先,实现 Serializable
与否究竟有什么差异
我认为,如果一个类不实现 Serializable 接口,直接的影响是无法使用 Java 原生的序列化方法对这个类进行序列化和反序列化。下面是将 Java 类写入到磁盘的例子
1 | SimpleUser user = new SimpleUser(); |
序列化后的 /tmp/user 文件如下
1 | ��sr%com.yuxisoft.meiyu.pojo.bo.SimpleUserIx���FdfullNametLjava/lang/String;LidtLjava/lang/Long;LversiontLjava/lang/Integer;xpt 李新宇srjava.lang.Long;��̏#�Jvaluexrjava.lang.Number��� |
序列化的前提是 SimpleUser
类实现了 Serializable
接口,否则会抛出 java.io.NotSerializableException
异常
serialVersionUID
的值可以改变吗
一般情况下不可以改变,会造成之前序列化好的对象无法反序列化,异常信息为 java.io.InvalidClassException
. 当然,如果不打算兼容以前的序列化产物,表名版本差异,可以对其进行更新
只实现 Serializable
接口而不定义 serialVersionUID
字段会怎样
如果不显式地定义 serialVersionUID
字段,jvm 会基于包名,类名,继承关系,非私有的方法和属性,以及参数,返回值等自动计算这个属性的值。因此,一旦类有修改,计算得到的 serialVersionUID
的值也必然发生改变,反序列化以前的序列化产物时同样会抛出 java.io.InvalidClassException
,因此实现 Serializable
接口,基本都要定义 serialVersionUID
字段
不实现 Serializable
接口的理由是什么
Java 原生的序列化和反序列化在实际项目中使用的频率很低甚至没有,在现在的 Java Web 项目中,一般都采用 Json 对 Java 对象进行封装和传输、解析,基本不会有对象直接以流的形式直接写入文件,然后读取的场景,实际开发过程中不实现 Serializable
完全没有任何问题
实现 OR 不实现,怎么选择
需要看情况,首先是确定项目中有没有使用 Java 原生序列化或者依赖的其它框架需要使用 Java 原生序列化的场景,如果没有,大可以不实现,但是实现了就一定要定义 serialVersionUID
字段。在写和不写都可以的情况下,看下团队其他成员的习惯,大家保持统一,目前来看实现这个 Serializable
接口要比不实现在某种程度上要政治正确
,但我认为团队内部也要理性,可能大家为了保持代码风格统一去写或者不写,但个人要正确地理解这一接口,做到心中有数
即可。