java文件中serialVersionUID 的用途

Java对象的serialVersionUID在序列化和反序列化的用途 本博客主要转自如下链接 http://blog.youkuaiyun.com/javazejian/article/details/52665164 这篇文章写的不错,但是有些地方我估计博主没有亲自测试,所以有些地方我亲测后发现其实他说的不对,大家可以先看看他写的,然后再看看我下面说的具体哪里不对了 先说说serialVersionUID的用途: 其实一个类要实现序列化和反序列化,不声明seria 阅读详情
一些java类中为什么需要重载 serialVersionUID 属性。
在Java中,软件的兼容性是一个大问题,尤其在使用到对象串行性的时候,那么在某一个对象已经被串行化了,可是这个对象又被修改后重新部署了,那么在这种情况下, 用老软件来读取新文件格式虽然不是什么难事,但是有可能丢失一些信息。
serialVersionUID来解决这些问题,新增的 serialVersionUID必须定义成下面这种形式:static final long serialVersionUID=-2805284943658356093L;。其中数字后面加上的L表示这是一个long值。 通过这种方式来解决不同的版本之间的串行化问题。

提纲:

━━━━━━━━

一、概述

二、Java串行化

三、引入版本编号

四、结束语

━━━━━━━━

一、概述

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

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

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

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

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

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

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

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

二、Java串行化

Java串行化有许多优点:

●容易使用。

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

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

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

public class Save implements Serializable
{
String name;

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



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

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



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

●类的名字(Save)。

●域的名字(name)。

●方法的名字(Save)。

●已实现的接口(Serializable)。

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

●static:该域定义的属性作用于整个类,而非特定的对象。

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

●long:它是一个64位的数值。

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

当然,改动之后的类不一定能够和原来的对象兼容。例如,如果把一个域的定义从String改成了int,执行逆-串行化操作时系统就不知道如何处理该值,显示出错误信息: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)的清单,这些清单指出了对类作了哪些改动之后仍可能读取原来串行化的数据。具体细节比较复杂,但了解其主要机制还是很容易的:
    简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。
当实现java.io.Serializable接口的实体(类)没有显式地定义一个名为serialVersionUID,类型为long的变量时,Java序列化机制会根据编译的class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID 。
如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,未作更改的类,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。
文章出处: http://www.diybl.com/course/3_program/java/javajs/2008419/110564.html
三、引入版本编号

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

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

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

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

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

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

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

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

四、结束语

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

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

撇开这些复杂的问题不谈,在实践中,很多时候我们只需简单的文件来保存数据,而且不会出现多用户并发访问,可以一次性地处理整个文件(或者至少适合使用顺序访问方式)。对于这些情形,最好在设计文件格式时就考虑版本问题,在日后的运行、维护中一定会带来不少方便。
单片机欠压保护、欠压复位的用法及作用 一. 前言 使用编程环境 :KEIL mdk4 单片机 : NRF24LE1   二. 分析 查询各开发芯片的数据手册,一般在电源管理或者复位设置章节中。以下NRF24LE1为例: Power supply supervisor(电源监控): 电源主管在开机时对系统进行初始化,对即将发生的情况提供预警当电源电压过低而不能安全运行时,系统处于复位状态。 电源管理框图如下:   ... 阅读详情

相关推荐

计算机组成原理汉字编码与校验设计实验报告(汉字国标码转区位码实验、汉字机内码获取实验、海明编码电路设计与海明解码)

这次实验利用logisim进行设计,进行了以下这四个实验,其中分为汉字国标码转区位码实验、汉字机内码获取实验、海明编码电路设计与海明解码,实验报告分为四个部分,在这四个部分中依次对四个实验的方案设计,设计思路进行了介绍

zhang2gongzi的博客 6万+

软件维护——Java文件格式之变化

一、概述 一个程序正式发行出去之后,如果要增加一些新的功能,往往意味着同时要修改用户保存数据的方式,也就是必须更改程序保存文件的格式——通常是增加保存到文件的数据。有些时候,文件格式必须作彻底的改动,以配合实现程序的新功能。从这个意义上看,文件格式的发展/变化总是和程序的功能改进相呼应。 但是,大多数情况下,把原有的数据格式一丢了事是行不通的。动物王国中,不能适应环境意味着死...

weixin_34004576的博客 325

LS-Dyna模态分析实战:从模型构建到结果解读的全流程指南

本文提供了一份详尽的LS-Dyna模态分析实战指南。文章系统讲解了如何利用LS-Dyna内置的隐式求解器进行特征值求解,从模型构建、几何清理、材料与连接设置,到核心的边界条件与隐式求解控制(如*CONTROL_IMPLICIT_EIGENVALUE),最后完成计算并解读频率与振型结果。旨在帮助工程师在熟悉的环境中高效完成结构振动特性分析,为后续动态响应分析奠定基础。

info6的博客 263

(转) serialVersionUID作用

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

qtlkw 364

SPECweb2009调优指南

 SPECweb2009 是衡量 Web 服务器性能和能效的标准化基准,可以对 Web 服务器的并发数进行性能测试,评测 Web 服务器能够支持的最大同时连接数的客户端/服务器(每秒能够响应的最大请求数)。为充分利用服务器性能,提升SPECweb2009测试结果,可通过增大系统进程数、优化服务器软件参数、绑核以及优化参数等。

developersupport的博客 2607

雾化器硬件设计:从N155驱动到PCB可量产实现

雾化器是典型的机电一体化嵌入式终端,其硬件设计本质是电源完整性、信号完整性与热-机械协同的系统工程。核心在于理解高压脉冲驱动原理(如2.4MHz固定频率匹配压电谐振)、电源域隔离机制(AGND/DGND/PGND分域设计)及约束驱动的PCB转化逻辑。技术价值体现在电气可靠性(如OTP/OLP保护)、生产可制造性(DFM合规焊盘与钢网)与环境鲁棒性(三防漆、散热过孔)。典型应用场景覆盖加湿器、医疗雾化仪与工业微流控设备。本文聚焦超声波雾化控制板的硬线实现路径,深入解析N155驱动芯片选型、网络标签工程误用陷阱

weixin_35649491的博客 618

java实体类中的序列化 和serialVersionUID

是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

qq_39187593的博客 1950

Cadence IC618/Spectre231安装避坑指南:详解License配置、环境变量隔离与依赖检查

本文详细介绍了Cadence IC618/Spectre231的安装与配置避坑指南,包括许可证系统精妙控制、环境隔离模块化实践、依赖管理进阶技巧以及长期维护的黄金法则。通过实战案例和解决方案,帮助工程师构建稳定可靠的EDA工作环境,提升芯片设计效率。

weixin_28683065的博客 461

serialVersionUID 报错

package com.test; import java.io.Serializable; public class Teacher  implements Serializable 125217 [ajp-8009-1] ERROR com.danga.MemCached.MemCachedClient - ++++ exception thrown while trying to get...

GuangRong1的博客 616

深入探究贝叶斯网络(Bayesian Network):从基础原理到实际应用

贝叶斯网络,也称为信念网络或有向无环图模型,是一种概率图模型。它使用有向无环图(DAG)来表示随机变量之间的条件依赖关系。每个节点代表一个随机变量,边表示变量之间的条件依赖关系。贝叶斯网络作为一种强大的工具,通过结合概率论和图论,为复杂系统建模和推理提供了有效手段。无论是在医学诊断、故障检测还是自然语言处理等领域,它都展示了巨大的潜力。然而,其计算复杂度高、结构学习困难等挑战也需要我们在实际应用中不断优化算法和技术。希望通过本文,你能对贝叶斯网络有更深入的理解,并能够在实际项目中灵活应用这一强大工具。

qq_28791753的博客 5971

OctoMag: An Electromagnetic System for 5-DOF Wireless Micromanipulation

电磁线圈组驱动经典系统,可以作为参考。 OctoMag: 用于5自由度无线微操作的一个电磁铁系统 OctoMag: An Electromagnetic System for 5-DOF Wireless Micromanipulation [1] Paper Link Authors: J. J. Abbott, etc. 2010, TRO IEEE Transactions on Robot...

XU Yangxin的博客 1665

【Java 基础篇】serialVersionUID 详解

是 Java 序列化机制中的一个字段,用于标识类的版本。当一个类实现了接口(表示该类可以被序列化),编译器会自动生成一个字段,用于表示类的版本号。是一个长整型数值,通常是一个正整数,可以手动指定,也可以由编译器自动生成。该字段的主要作用是用于在反序列化时检查类的版本是否与序列化时的版本一致,以确保反序列化的对象与序列化时的对象是兼容的。当使用进行版本控制时,通常需要考虑以下情况:当类的版本发生变化时,如何确保反序列化仍然能够成功。以下是一个示例,演示了如何使用处理不同版本类的序列化和反序列化。

繁依Fanyi的博客 1万+

PTC Creo软件二次开发:使用C++进行Creo二次开发实战

C++是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。由Bjarne Stroustrup在贝尔实验室开发,最初作为C语言的增强版出现,后来发展成为一种独立的语言。C++不仅保留了C语言的高效性和灵活性,还引入了类、模板、命名空间等高级特性,使其成为开发复杂系统和软件的理想选择。

kkchenjj的博客 4043

java文件中serialVersionUID 的用途<转帖>

一些java类中为什么需要重载 serialVersionUID 属性。 在Java中,软件的兼容性是一个大问题,尤其在使用到对象串行性的时候,那么在某一个对象已经被串行化了,可是这个对象又被修改后重新部署了,那么在这种情况下, 用老软件来读取新文件格式虽然不是什么难事,但是有可能丢失一些信息。 serialVersionUID来解决这些问题,新增的serialVersionUID必须定义成...

Walking In Thinking 139

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Java对象为啥要实现Serializable接口?

为什么一定要实现Serializable接口? 它的底层原理是什么? 为什么一定要序列化? 序列化又是什么? 1、Serializable接口概述 Serializable是java.io包中定义的,用于实现Java类的序列化操作而提供的一个语义级别的接口。Serializable序列化接口没有任何方法或者字段,只是用于标识可序列化的语义。实现了Serializable接口的类可以被ObjectOutputStream转换为字节流,同时也可以通过ObjectInputStream再将其解析为对象。

weixin_40482816的博客 768

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

重要接口—Serializable接口

一、Serializable //标识接口:空接口 //标志接口的作用:让JVM去实现 public interface Serializable{} 作用: https://tech.meituan.com/2015/02/26/serialization-vs-deserialization.html 二、Cloneable 三、Map<K,V> 四、NavigableMap<K,V> 五、SortedMap<K,V> ...

sanmi8276的博客 623

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Serializable 接口(序列化)

目录 Serializable 接口(序列化) 前言 用途 如何实现 异常 serialVersionUID transient关键字 Serializable 接口(序列化) 前言 查看API文档时...

weixin_30344131的博客 102

java中serialversionuid的用途

一些java类中为什么需要重载 serialVersionUID 属性。  在Java中,软件的兼容性是一个大问题,尤其在使用到对象串行性的时候,那么在某一个对象已经被串行化了,可是这个对象又被修改后重新部署了,那么在这种情况下, 用老软件来读取新文件格式虽然不是什么难事,但是有可能丢失一些信息。  serialVersionUID来解决这些问题,新增的serialVersionUID必须定义

不知道要什么,便什么都想要,最后什么都要不到 808

什么是serialVersionUID?serialVersionUID详解

在阅读很多开源项目中在很多类中都会发现存在一个使用static final 修饰的量,通常很大而且和代码似乎没有什么规律。 比如下面的代码: public class Dml implements Serializable { private static final long erialVersionUID = 2611556444074013268L; (代码来自阿里巴巴开源项目Client Adapter) 概述 所述的serialVersionUID属性是用来序列的标识符/反序列化的对象

北鹤M的代码手账 4万+

serialVersionUID 的用途及未定义的影响:深入探讨与实际应用

作为一名编程博客专家,我将带领大家深入探讨的用途及其在 Java 序列化中的重要性。本文将详细解释的含义、用途以及未定义可能带来的问题。通过丰富的代码示例、代码注释和技术解释,帮助程序员全面理解的工作原理及实际应用。如果类没有定义,JVM 会在运行时自动生成一个。然而,自动生成的通过本文的讲解,我们详细了解了的用途及其在 Java 序列化中的重要性。用于标识类的版本,确保序列化数据与当前类的版本兼容。未定义可能会导致版本不兼容和运行时错误。在实际编程中,定义。

xycxycooo的博客 946

java文件中为什么会有serialVersionUID

[转自: http://tbase.itpub.net/post/4931/42269] java文件中为什么会有serialVersionUID 。 一些java类中为什么需要重载 serialVersionUID 属性。 在Java中,软件的兼容性是一个大问题,尤其在使用到对象串行性的时候,那么在某一个对象已经被串行化了,可是这个对象又被修改后重新部署了,那么在这种情况下, 用

做好当下 711

Java中serialVersionUID作用

聊聊序列化接口java.io.Serializable和serialVersionUID

Keep learing, and stay fast 2708

Java中 serialVersionUID 有啥用?

根据父类对象序列化的规则,我们可以将不需要被序列化的字段抽取出来放到父类中,子类实现 Serializable 接口,父类不实现,根据父类序列化规则,父类的字段数据将不被序列化,形成类图如图 2 所示。Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。【答案】序列化,反序列化正常,B端字段少于A端,A端多的字段值丢失(被B端忽略)。

2401_87254629的博客 872

java类中serialVersionUID的作用

原文出处:https://www.cnblogs.com/duanxz/p/3511695.html实现Serializable接口的目的是为类可持久化,比如在网络传输或本地存储,为系统的分布和异构部署提供先决条件。若没有序列化,现在我们所熟悉的远程调用,对象数据库都不可能存在,serialVersionUID适用于java序列化机制。简单来说,JAVA序列化的机制是通过判断类的serialVer...

u014750606的博客 22万+

java中SerialVersionUID的作用

我们在进行java后端开发的过程中,经常会看到如下的代码片段: package com.shijia.apidemo.pojo; import java.io.Serializable; import java.sql.Time; import java.util.Date; /** * 系统用户信息 */ public class SysUser implements Serializable { private static final long serialVersionUID

白不懂黑的静的专栏 455
上一篇: (转)如何才算掌握Java
下一篇: SVN提交工作注意事项(转载)
wang12
博客等级 码龄24年 39粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值