当前位置: 首页 > news >正文

序列化 serialVersionUID

原文出处:未知

 

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改为不一样,不能直接的复制粘贴过来。

转载于:https://www.cnblogs.com/a-blue/p/3825452.html

相关文章:

  • windows下的套接字IO模型
  • 第一周考试总结
  • ExtJs中组件最好少使用ID属性(推荐更多使用Name属性)
  • 读书笔记-《JavaScript高级程序设计(第3版)》
  • ASP.NET MVC Model验证(一)
  • OpenCV+python轮廓
  • Objective-C语法之NSSet和NSMutableSet
  • 孤独与寂寞
  • 人工智能火了,为啥医疗成为最先受益者?
  • Java反射机制简单了解_Reflection
  • 前端 图表
  • Linux系统备份与还原
  • 如何使用 Gin 和 Gorm 搭建一个简单的 API 服务 (一)
  • java 获取HttpRequest Header 的几种方法 请求request的所有参数实现方法
  • SolrCould 集群搭建
  • [译]CSS 居中(Center)方法大合集
  • Github访问慢解决办法
  • go语言学习初探(一)
  • Invalidate和postInvalidate的区别
  • JavaScript 基础知识 - 入门篇(一)
  • Java程序员幽默爆笑锦集
  • js如何打印object对象
  • MD5加密原理解析及OC版原理实现
  • python大佬养成计划----difflib模块
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • Vue 2.3、2.4 知识点小结
  • 程序员该如何有效的找工作?
  • 分布式事物理论与实践
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 推荐一个React的管理后台框架
  • gunicorn工作原理
  • 第二十章:异步和文件I/O.(二十三)
  • 移动端高清、多屏适配方案
  • # C++之functional库用法整理
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (3)STL算法之搜索
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (C语言)fread与fwrite详解
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Java)【深基9.例1】选举学生会
  • (ros//EnvironmentVariables)ros环境变量
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .htaccess 强制https 单独排除某个目录
  • .htaccess配置重写url引擎
  • .net web项目 调用webService
  • .Net6 Api Swagger配置
  • .net通用权限框架B/S (三)--MODEL层(2)
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(朱雀组)
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt