Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。

  Eclipse中The serializable class XXXXXX does not declare a static final serialVersionUID field of type long出现这样的警告处理办法。

  当采用程序的Add default Serial version ID修复时,Eclipse会加上:private static final long serialVersionUID = 1L;

  当采用程序的Add generated Serial version ID修复时,Eclipse会加上:private static final long serialVersionUID = xxxxL;

  其实这个问题出现的具体原因是和序列化中的这个serialVersionUID有关。

  serialVersionUID 用来表明类的不同版本间的兼容性。有两种生成方式:

  一个是默认的1L,比如:private static final long serialVersionUID = 1L;(对应修复方法1)

  一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如: 
private static final long serialVersionUID = xxxxL;(对应修复方法2)

  在JDK中,可以利用JDK的bin目录下的serialver.exe工具产生这个serialVersionUID 的值,对于Test.class,执行命令: 
serialver Test   这时JVM(java虚拟机)会生成一个哈希字段。

  对比一下这个哈希字段的值与方法2中生成的字段值是一样的,可见,在CMD中使用serialver指令就是根据类名、接口名、成员方法及属性等来生成哈希字段的。

下面来讨论java类中为什么需要重载 serialVersionUID 属性。

  当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。

  把Java对象转换为字节序列的过程称为对象的序列化。

  把字节序列恢复为Java对象的过程称为对象的反序列化。

  对象的序列化主要有两种用途:

  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

  2) 在网络上传送对象的字节序列。

  java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

  java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

  只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式 。

  凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:private static final long serialVersionUID;

  类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。显式地定义serialVersionUID有两种用途:

  1)在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

  2)当你序列化了一个类实例后,希望更改一个字段或添加一个字段,不设置serialVersionUID,所做的任何更改都将导致无法反序化旧有实例,并在反序列化时抛出一个异常。如果你添加了serialVersionUID,在反序列旧有实例时,新添加或更改的字段值将设为初始化值(对象为null,基本类型为相应的初始默认值),字段被删除将不设置。

  当系统不需要序列化类时,可以去掉这些警告,做如下设置:Window-->Preferences-->Java,将serializable class without serialVersionUID的设置由warning改为Ignore。然后Eclipse会重新编译程序,那些警告信息也就消失了。

  struts架构下的网站经常出现javax.servlet.ServletException: BeanUtils.populate 错误,但是本地运行又一切正常,唯一觉得可能产生问题的就是服务器上跑了好几个网站,都是一样的架构的,怀疑是不是web容器把几个项目之间的java类给共用了,考虑到很多类都定义了serialVersionUID字段,然后尝试删除了某个类的serialVersionUID,结果关于该类的操作就恢复正常了。网上简单查阅了一下资料,感觉是tomcat把所有类串行化时候,由于我们的几个项目很多java类都是复制粘贴的,所以导致了很多类的serialVersionUID都是同一个值,所以tomcat会把不同项目的相同类名的类当作同一个类去处理,导致了这个奇怪的错误。

解决方案: 
  每个项目同名的类serialVersionUID改为不一样,不能直接的复制粘贴过来。

serialVersionUID的作用的更多相关文章

  1. serialVersionUID, ObjectInputStream与ObjectOutputStream类,Serializable接口,serialVersionUID的作用和用法

    ObjectInputStream与ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入 Ser ...

  2. serialVersionUID的作用 (zz)

    serialVersionUID的作用 2011-05-12 16:04:19|  分类: java|举报|字号 订阅     在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘 ...

  3. serialVersionUID的作用以及设置方法(转)

    声明:本篇文章是转载的 http://blog.csdn.net/kakaxi_77/article/details/8129070 http://snowlotus.iteye.com/blog/2 ...

  4. serialVersionUID的作用以及如何用idea自动生成实体类的serialVersionUID

    转载:http://blog.csdn.net/liuzongl2012/article/details/45168585 serialVersionUID的作用: 通过判断实体类的serialVer ...

  5. 序列化与反序列化中serialVersionUID的作用(通俗易懂)

    serialVersionUID:字面意思上是序列化的版本号,这个在刚刚接触java编程时,学序列化大家一般都不会注意到,在你一个类序列化后除非你强制去掉了myeclipse中warning的功能,在 ...

  6. serialVersionUID的作用以及IDEA、Eclipse如何自动生成serialVersionUID

    说到serialVersionUID,首先要讲讲序列化. 序列化: 序列化可以将一个java对象以二进制流的方式在网络中传输并且可以被持久化到数据库.文件系统中,反序列化则是可以把之前持久化在数据库或 ...

  7. 定义serialVersionUID的作用与意义整理

    实现java.io.Serializable这个接口是为序列化,serialVersionUID 用来表明实现序列化类的不同版本间的兼容性.如果你修改了此类, 要修改此值.否则以前用老版本的类序列化的 ...

  8. 【Struts中private static final long serialVersionUID的作用】

     private static final long serialVersionUID = -1672970955045193907L;   SerialVersionUID,后面简称SUID 其实序 ...

  9. 静态long类型常量serialVersionUID的作用

    需要序列化的类需要实现Serializable接口,该接口没有任何方法,只是标示该类对象可被序列化. 序列化过程:使用一个输出流(如:FileOutputStream)来构造一个ObjectOutpu ...

随机推荐

  1. Android中的Context

    Context用来访问全局信息的接口,比如影城程序的资源.一些常用的组件都是继承自Context,目的就是方便的访问资源,比如Activity, Service.... 从Context访问本组件的资 ...

  2. Shell脚本8种字符串截取方法总结

    Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.aaa.com/123.htm. 1. # 号截取,删除左边字符,保留右边字符. 代码如下: echo ${va ...

  3. CALayer笔记

    1.Core Animation是跨平台的,支持IOS和Mac OS X环境 2.核心动画操作的对象不是UIView而是CALayer,CALayer是核心动画的基础, 可以做圆角.阴影.边框等效果 ...

  4. odi 12.2.1中访问excel文件

    由于在odi 12.2.1中,必须使用jdk1.8,而jdk1.8中jdbc-odbc bridge已经不再支持,因此,可以使用Progress DataDirect SequeLink来充当jdbc ...

  5. 让低版本IE支持css3背景图片缩放属性background-size

    IE7,8中不支持背景图片的缩放.下面的代码可以帮你实现兼容 background: url(/content/img/yuehuibtn.png);//css3代码 background-size: ...

  6. 第9章 硬件抽象层:HAL

    HAL(硬件抽象层)是建立在Linux驱动之上的一套程序库.这套程序库并不属于Linux内核,而是属于Linux内核层之上的应用层.在传统的Linux系统中Linux驱动一般有两种类型的代码:访问硬件 ...

  7. Java的多态

    多态的定义: 同一种行为,在不同对象上有不同的表现形式 实现多态的条件: 要有继承 要有方法的重写 要有父类的引用指向子类的对象 代码如下: public class Animal { String ...

  8. win7 32 bit VS2012 OpenCV3.0配置

    今天看CPP基础,想起来之前在vs2012配置opencv3未成功,就忍不住再次配置一... 环境:win7 32bit vs2012 opencv3.0 主要参考这几篇博文:1,2,3 上面的博文已 ...

  9. Freemark基本语法知识(转)

    FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:<#-- ... -->格式部分,不会输 ...

  10. BackTrack5-r3汉化

    进入BT系统图形模式,将语言包1和2拖进BT图形桌面. 所需文件包地址:http://pan.baidu.com/s/1i3ouc9v(64位更新包)将语言包1里的全部文件复制粘贴到:/var/cac ...