SerialVersionUID [Java]
SerialVersionUID
SerialVersionUID就是一个静态常量
一般都是声明在一个可序列化的类中,并且一般都是显示的进行声明
声明的格式一般为:
private static long SerialVersionUID = xxxxxxxxxxxxxxxxxxxxxL
SerialVersionUID用来表示类的不同版本的兼容性,以序列化对象进行版本控制,有关对象反序列化时是否兼容
如果没有显示的在类中声明这个静态常量,那么java运行时环境(jre)会根据类的内部细节自动进行生成
- 但是如果是java运行时环境自动生成的SerialVersionUID,那么这个时候如果我们对这个类的实例变量进行了修改,这个时候java运行时环境会重新生成一个SerialVersionUID ---- 也就是如果我们没有显示的声明这个静态常量,那么这个常量就有可能发生改变
- 所以我们最好显示的声明这个静态常量
难点思路分析:
如果一个Person类没有显示的声明SerialVersionUID,但是这个类实现了Serializable接口,这个时候我们对Person类的一个对象进行了序列化(也就是将这个对象持久化到了硬盘中),然后我们在这个类中多定义一个成员变量,然后再进行反序列化,这个时候就不能将原本的对象从硬盘中还原回来了,这个时候会抛出一个运行时异常 — java.io.InvalidClassException
那么为什么反序列化会失败?
因为在序列化之后,反序列化之前我们对这个类中的成员变量进行了修改(也就是修改了实例变量),这个时候这个类的序列化ID(SerialVersionUID)就会跟着发生改变,这个时候我们虽然将原本未修改的类的对象持久化存储到了硬盘中,但是这个时候我们反序列化的时候由于序列化ID发生了改变,这个时候就找不到原本的Person类了,这个时候也就自然反序列化失败了 — 也就相当于我们持久化存储的时候是将这个对象的一些基本的信息存储到了硬盘中,这个时候我们的类就是模板,我们想要反序列化这个时候先要找到模板,然后根据这个模板,然后加上零件,这个时候才可以合成一个对象 – 而这个时候我们只有硬盘中的文件,也就是只有零件 , 由于序列化ID发生了改变,这个时候不能找到对应的类,这个时候就没有模板,自然就合成不成一个java对象了
对应思路我们给出一个例题:
这里我们先提供一个Person类
- 首先,这个Person类实现Serializable接口(Serializable接口是一个标识接口 — 标识可以序列化的类)
- 其次,这个类中我们不显示的提供SerialVersionUID
package IO流.SerialVersionUID;import java.io.Serializable;public class Person implements Serializable{private String name;private int age;//无参构造方法public Person(){}//有参构造方法public Person(String name, int age){this.name = name;this.age = age;}/*对应私有属性的get和set方法*/public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//重写toSting()方法@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
然后我们以这个Person类为模板创建一个对象,将这个类的对象序列化到硬盘中
package IO流.SerialVersionUID;import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.File;
import java.io.IOException;public class Demo1 {public static void main(String[] args) throws IOException{//创建Person类的对象Person p = new Person("飞飞",14);/*创建对象输出流对象注意: 虽然大多的处理流创建对象时都不会抛出异常,但是我们的对象输入输出流会抛出IOException*/ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("Person2.dat")));/*将我们的Person类型的对象p序列化到硬盘中*/oos.writeObject(p);/*流资源的关闭*/oos.close();}
}
然后我们再对Person类进行修改: 我们给Person类添加一个成员变量:private int id
package IO流.SerialVersionUID;import java.io.Serializable;public class Person implements Serializable{private String name;private int age;//添加的成员变量: private int idprivate int id;//无参构造方法public Person(){}//有参构造方法public Person(String name, int age){this.name = name;this.age = age;}/*对应私有属性的get和set方法*/public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//重写toSting()方法@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
最后我们再进行反序列化得到我们持久化存储到硬盘中的Person类的对象
package IO流.SerialVersionUID;import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.File;
import java.io.IOException;
//java.lang包中的内容会自动导入,但是为了清楚,还是手动到了一次,实际编程中不需要再导入
import java.lang.ClassNotFoundException;public class Demo2 {public static void main(String[] args) throws IOException,ClassNotFoundException{//创建对象输入流对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("Person2.dat")));/*从文件中进行反序列化,尝试得到Person类的对象注意: 对象输入流的readObject()方法不但会抛出IOException,还会抛出ClassNotFoundException*/Person p = (Person)ois.readObject();/*输出Person类的对象p*/System.out.println(p);/*流资源的关闭*/ois.close();}
}
- 这个时候进行反序列化的时候会抛出一个java.io.InvalidClassException
那么我们如何避免这种情况的发生呐?
我们只需创建Person类的时候显示的提供SerialVersionUID就可以了
- 我们只要显示的提供了SerialVersionUID,这个时候不管我们的Person类如何改变,这个时候这个类的序列化版本号都不会发生改变 — 也就不会出现这种异常
SerialVersionUID [Java]相关推荐
- 【重难点】【Java基础 04】值传递和引用传递、序列化和反序列化
[重难点][Java基础 04]值传递和引用传递.序列化和反序列化 文章目录 [重难点][Java基础 04]值传递和引用传递.序列化和反序列化 一.值传递和引用传递 1.对比 二.序列化 1.基本概 ...
- HowToDoInJava Java 教程·翻译完成
原文:HowToDoInJava 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远. ApacheCN 学习资源 目录 核心 Java 教程 什 ...
- java transient关键字_嗯?你真的会用 Java 序列化机制?
码农每日一题长按关注,工作日每天分享一个技术知识点. 一.序列化.反序列化概念及其使用场景 1.序列化.反序列化的概念 简单的讲,序列化就是将java对象转化成二进制保存到磁盘中去,反序列化就是从磁盘 ...
- JAVA:JDK目录结构和文件作用介绍
要想深入了解Java必须对JDK的组成, 本文对JDK6里的目录做了基本的介绍,主要还是讲解 了下JDK里的各种可执行程序或工具的用途 Java(TM) 有两个平台 JRE 运行平台,包括Java虚拟 ...
- Java初级知识复习-2021.12.27~2022.02.09
文章目录 Java语法基础1 1.Java简介 Java三大版本含义 Java的特性和核心优势 2.Java开发环境配置 Java应用程序的运行机制 开发环境搭建 3.Java基础语法 4.Java基 ...
- “万字“ Java I/O流讲解
Java I/O流讲解 每博一文案 谁让你读了这么多书,又知道了双水村以外还有一个大世界,如果从小你就在这个天地里,日出而作,日落而息. 那你现在就会和众乡亲抱同一理想:经过几年的辛劳,像大哥一样娶个 ...
- Spring Cache-缓存概述及使用
概述 缓存的概念 缓存命中率 过期策略 Spring Cache的好处 Spring Cache的缺点 自定义缓存管理器粗略实现 使用Spring Cache 示例源码 概述 伴随信息量的爆炸式增长以 ...
- 22(2)序列化以及反序列化
序列化:把要传输的对象以及相关信息转成对应的字节数组进行存储 反序列化:把字节数组转回成相应的对象 主要作用于数据传输 如果把要传输的对象以及相关信息(非静态属性)转成对应的字节数组进行存储,并把该字 ...
- c语言变量类型int,C语言基础学习基本数据类型-int类型与int变量
C++学习笔记26:泛型编程概念 一.什么是泛型编程? 泛型就是通用的型式 编写不依赖数据对象型式的代码就是泛型编程 二.为什么需要泛型编程? 函数重载,相似类定义与型式兼容性 例如:设计函数,求两个 ...
- java 中的 serialVersionUID
2019独角兽企业重金招聘Python工程师标准>>> private static final long serialVersionUID = 1L; Java的序列化机制是通过判 ...
最新文章
- 1002: A+B for Input-Output Practice (II)
- 023_jdbc-mysql的CRUD操作
- 2013ACM暑假集训总结-致将走上大三征途的我
- 43、Java动态代理一——动态类Proxy的使用
- 『ACM--算法--KMP』信息竞赛进阶指南--KMP算法(模板)
- 创建基于AJAX技术的Scribble应用程序
- docker 安装 oracle12,Centos7下利用docker安装oracle12c
- Python实现最简单的神经网络(数字识别)
- mysql技术blog_Mysql技术 - 包子博客 _ 关注互联网前端、开发、SEO、移动互联网应用技术...
- 拓端tecdat|R语言时变向量自回归(TV-VAR)模型分析时间序列和可视化
- 高斯混合模型及python代码
- R语言拟合ARIMA模型
- 微信h5开发遇到的小问题
- 蓝桥杯 java 楼梯,递归1之楼梯问题
- Python合并pdf文件
- 正则表达式 正则表达式语法
- 怎么做简单版ps碎片飞溅效果
- 通过HTML和CSS制作二级菜单栏
- android实现首页倒计时,Android倒计时 Android仿京东倒计时 android电商app源码倒计时源码...
- html5小游戏跑,HTML5 Speedster 小游戏(高速跑跳过关)