java重载:java 文件中为什么要重载 serialVersionUID 属性

些java类中为什么需要重载 serialVersionUID 属性

在Java中软件Software兼容性是个大问题尤其在使用到对象串行性时候那么在某个对象已经被串行化了可是这个对象又被修改后重新部署了那么在这种情况下 用老软件Software来读取新文件格式虽然不是什么难事但是有可能丢失些信息

serialVersionUID来解决这些问题新增serialVersionUID必须定义成下面这种形式: final long serialVersionUID=-2805284943658356093L;其中数字后面加上L表示这是个long值 通过这种方式来解决区别版本的间串行化问题


提纲:

━━━━━━━━

、概述

2、Java串行化

3、引入版本编号

4、结束语

━━━━━━━━

、概述

正式发行出去的后如果要增加些新功能往往意味着同时要修改用户保存数据方式也就是必须更改保存文件格式——通常是增加保存到文件数据有些时候文件格式必须作彻底改动以配合实现新功能从这个意义上看文件格式发展/变化总是和功能改进相呼应

但是大多数情况下把原有数据格式丢了事是行不通动物王国中不能适应环境意味着死亡;软件Software领域也相似新软件Software是否支持原有数据格式很大程度上决定了用户是否升级

不管软件Software新增/改进了多少功能不管新文件格式是多么完美如果新软件Software不能利用原来文件格式用户般不太会认可新软件Software解决该问题办法包括:

●保留老代码来读取老文件采用这种方案般需要额外编写些代码把老文件转换成新格式(般地最简单办法是先把老文件数据转换成新内部对象然后利用现有写入新版文件格式对象)这种办法好处是既保留了原有代码又使它和新文件格式兼容但是这种办法有时可能导致丢失部分数据不过总要比丢失全部数据好

●使新版软件Software能够读/写老文件格式这种办法工作量较大新版本般会增加些原来没有功能数据格式中通常缺乏新功能必需某些数据

当新版软件Software对原来执行任务方式作了根本性变动时丢失数据决非难得偶然事件如果新版软件Software采用和原来区别方式达到同样效果原来功能可能不再有保留必要例如如果原来用Swing做用户界面现在把它改成了Web(浏览器)用户界面原来许多用户界面设置就不再有效

又如如果有个邮件原来用是以文件夹为基础索引现在把它改成了以单词为基础索引系统在升级索引文件格式过程中就有可能丢失许多信息;如果原来索引文件保存了许多用户配置选项和优化措施在新索引系统中这些数据可能无法利用

这类问题没有绝对完美解决办法但是我们可以采取些措施使得升级文件格式带来负面影响尽可能小Java串行化(Serialization)有着简单易用特点日益成为种保存文件重要手段有鉴于此下面我们就来看看在软件Software版本变更过程中通过Java串行化保存文件如何保持兼容性

2、Java串行化

Java串行化有许多优点:

●容易使用

●如果个对象连接到其他对象串行化机制会保存所有相关对象

●如果某个对象出现多次串行化机制只保存点极为重要它不仅减小了文件空间而且即使代码写得不是很老练也不必担心会出现无限循环(个不老练例子是用递归方式保存各个对象却又未能有效审计哪些对象已经保存这时就有可能陷入永无终止循环)

遗憾Java串行化机制定义文件格式似乎很脆弱只要稍微改动下类定义原来保存对象就可能无法读取例如下面是个简单类定义:

public Save implements Serializable
{
String name;

public void save throws IOException
{
FileOutputStream f = FileOutputStream("foo");
ObjectOutputStream oos = ObjectOutputStream(f);
oos.writeObject(this);
oos.close;
}
}



如果在这个类定义中增加个域例如final val = 7;再来读取原来保存对象就会出现下面异常:

java.io.InvalidClassException:
Save; local incompatible:
stream desc serialVersionUID = -2805284943658356093,
local serialVersionUID = 3419534311899376629



上例异常信息中数字串表示类定义里各种属性编码值:

●类名字(Save)

●域名字(name)

●思路方法名字(Save)

●已实现接口(Serializable)

改动上述任意项内容(无论是增加或删除)都会引起编码值变化从而引起类似异常警报这个数字序列称为“串行化版本统标识符”(serial version universal identier)简称UID解决这个问题办法是在类里面新增个域serialVersionUID强制类仍旧使用原来UID新增域必须是:

:该域定义属性作用于整个类而非特定对象

●final:保证代码运行期间该域不会被修改

●long:它是个64位数值

也就是说新增serialVersionUID必须定义成下面这种形式: final long serialVersionUID=-2805284943658356093L;其中数字后面加上L表示这是个long值

当然改动的后类不定能够和原来对象兼容例如如果把个域定义从String改成了执行逆-串行化操作时系统就不知道如何处理该值显示出信息:java.io.InvalidClassException: Save; incompatible types for field name

Java串行化规范标准(http://java.sun.com/j2se/1.4.1/docs/guide/

serialization/spec/serialTOC.doc.html)提供了有关兼容改动(http://java.sun.com/j2se/1.4.1/docs/

guide/serialization/spec/version.doc7.html)和不兼容改动(http://java.sun.com/j2se/1.4.1/docs/guide/

serialization/spec/version.doc8.html)清单这些清单指出了对类作了哪些改动的后仍可能读取原来串行化数据具体细节比较复杂但了解其主要机制还是很容易:





简而言的如果文件中确实保存了所有必需数据那么仍有可能读取该文件当然前提是必须处理好串行化UID

3、引入版本编号

许多都在无意的中作出了这样假设:这种文件格式是我要用到最后种格式以后不再需要制定新格式现在要做是处理好在此的前各种格式这种会试图读取格式版本更高文件操作进行到半才发现某些不能识别数据然后就是突然崩溃如果文件包含了大量元数据(描述文件本身数据)处理起来就要容易得多

在Java中个域都由其名称显式标明只要文件改动不是很大(只添加了域没有被删除或作重大更改域)可以想象用老软件Software来读取新文件格式不是什么难事虽然有可能丢失些信息但可以搞清楚文件基本情况

文件格式随着功能改变而改变理想情况下应当做到既向后兼容(新版本能够按照老版本格式读取甚至可能允许更新)同时做到向前兼容(较老软件Software能够识别和处理新版文件格式)

通常文件版本无法从表面上眼看出大多数不会文件版本区别而更改文件扩展名而且目前尚无统标记文件版本办法因此有关文件格式版本声明只能在文件本身的内进行如果你现在使用文件格式还不包含版本声明最好在下次把文件升级成个不兼容版本时马上加入版本标记或者寻求种在当前文件格式中加入版本标记但不会带来负面影响办法

版本信息般在文件开头声明这是必须在处理文件的前首先检查文件版本除非确定了文件版本否则不必读取文件其余部分

按照惯例文件版本编号包含两个部分:主版本编号和次版本编号个特定版本应当有最适合它处理主-次版本号;主版本号变化意味着文件格式重大变化要继续使用已经非常困难必须作出重大修改才能升级到新版本

文件主次版本号的前往往还可以加入另项内容称为“魔术数字”作用就是保证处理文件类型不会有误(文件扩展名有可能不能唯地标明文件类型)例如Java类文件总是以下列字节内容开头(十 6进制):CA FE BA BE目前还没有这类数字注册机构不过UNIX在/etc/magic下提供了个清单(但并不完整)魔术数字般有 4个字节取值范围很大所以般不必担心会出现取值冲突情形

在编写和维护必须读/写文件代码时注意代码向前/向后兼容性是非常必要在处理文件代码中首先读取文件版本然后根据版本号将文件剩余内容传递给适当处理思路方法;如果文件版本太老已不再支持应当给出明确提示

4、结束语

文件格式设计是个极其重要话题但本文还有许多细节问题尚未涉及例如对于大型文件我们需要随机访问而不是从前向后依次读取文件内容顺序访问这样就不必为了访问文件最后几个字节而读取整个文件无论是XML还是Java串行化对这类随机访问支持都不是很理想而且这类文件格式发展变化比普通文件更难管理他们依赖于字节级访问稍微改动下文件格式就可能导致不兼容

如果要让文件具有ACID特性——Atomicity、Consistency、Isolation和Durability即原子性、致性、隔离性、持久性问题更加复杂ACID和事务概念密切相关支持多用户同时访问个文件对于这类文件可以考虑采用某种小型数据库系统例如Birdstep或Sleepycat不过这已经进入了文件格式管理个领域既涉及到数据库管理软件Software版本也涉及到数据模式设计版本

撇开这些复杂问题不谈在实战中很多时候我们只需简单文件来保存数据而且不会出现多用户并发访问可以次性地处理整个文件(或者至少适合使用顺序访问方式)对于这些情形最好在设计文件格式时就考虑版本问题在日后运行、维护中定会带来不少方便
Tags:  java方法的重载 java中的重载 java方法重载 java重载

延伸阅读

最新评论

发表评论