在用Eclipse进行编程,尤其是到后面往往一个项目涉及多个类的时候,我发现我在进行编程时总会在类名的那一行出现一个警告信号关于“The
serializable class XXX does not declare a static final
serialVersionUID field of type long”
我刚开始忽略它,因为它并不影响程序的执行。
但当大量的程序代码均显示这个警告的时候我觉得有必要弄清原因。
查找资料后,我大致理清了其出现的原因和解决方法。
1)首先,我先引入一个概念——序列化。
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
把Java对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为Java对象的过程称为对象的反序列化。
对象的序列化主要有两种用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
实用意义
一:对象序列化可以实现分布式对象。
主要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。
二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络
连接上传递。利用对象序列化可以进行对象的“深复制”,即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
以下内容我觉得有助理解序列化这一抽象概念,如果感兴趣,可以看一下
2)JAVA中如何实现序列化
简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。
类通过实现 java.io.Serializable
接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
3)Eclipse为何因序列化问题提出警告
当实现java.io.Serializable接口的实体(类)没有显式地定义一个名为serialVersionUID,类型为long的变量时,Java序列化机制会根据编译的class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID
。(这是当我们没有显式定义serialVersionUID时导致的)
如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本(所谓的向后兼容),未作更改的类,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。
同时,为了在反序列化时,确保类版本的兼容性,最好在每个要序列化的类private static final long serialVersionUID这个属性,具体数值自己定义。这样,即使某个类在与之对应的对象已经序列化出去后做了修改,该对象依然可以被正确反序列化。否则,如果不显式定义该属性,这个属性值将由JVM根据类的相关信息计算,而修改后的类的计算结果与修改前的类的计算结果往往不同,从而造成对象的反序列化因为类版本不兼容而失败。
此外,不显式定义这个属性值的另一个坏处是,不利于程序在不同的JVM之间的移植。因为不同的编译器实现该属性值的计算策略可能不同,从而造成虽然类没有改变,但是因为JVM不同,出现因类版本不兼容而无法正确反序列化的现象出现。
到此可以看出虽然其不影响我们程序的执行,但Eclipse处于谨慎考虑仍会警告以希望我们显式定义这一属性。
4)解决方法
这要看你所编写的类是否有序列化必要,一般需要序列化的是以下几种情况:
a)当你想把的内存中的对象保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;(RMI的百度百科http://baike.baidu.com/view/1227687.htm)
在这里我先提一种简单的序列化解决方法,就是点击Eclipse在类上的警告信号,采用其的解决方案,即显式加上一个private
static final long
serialVersionUID。如果想要了解更复杂的方法进行具体定义,可以去搜索关于java.io.Serializable的资料。
如果编写的程序都没有太大必要进行这个显式定义,可以在Eclipse中进行如下设置:Window-->Preferences-->Java,将serializable
class without
serialVersionUID的设置由warning改为Ignore。以此来取消这一警告。(不建议)
毕竟只是入门,原本只是想简单找找相关资料,结果引出了一大堆,上面只是粗略的整理和综合,以后随着深入学习我会慢慢修改和完善这篇文章,先让对此问题有兴趣的同学能有个入门的了解,然后大家一起逐渐地补充和订正,也请老师帮忙修正理解上的缺陷。
——周雅