本文系转载,原文链接:http://swiftlet.net/archives/1268

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

serialVersionUID有两种显示的生成方式:        
一是默认的1L,比如:private static final long serialVersionUID = 1L;        
二是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:        
private static final  long   serialVersionUID = xxxxL;

当一个类实现了Serializable接口,如果没有显示的定义serialVersionUID,Eclipse会提供相应的提醒。面对这种情况,我们只需要在Eclipse中点击类中warning图标一下,Eclipse就会      自动给定两种生成的方式。如果不想定义,在Eclipse的设置中也可以把它关掉的,设置如下:
Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==> Potential programming problems
将Serializable class without serialVersionUID的warning改成ignore即可。

当实现java.io.Serializable接口的类没有显式地定义一个serialVersionUID变量时候,Java序列化机制会根据编译的Class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,如果Class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释等等),就算再编译多次,serialVersionUID也不会变化的。

如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。

下面用代码说明一下serialVersionUID在应用中常见的几种情况。

(1)序列化实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

import java.io.Serializable;
public class Person implements Serializable
{
    private static final long serialVersionUID = 1234567890L;
    public int id;
    public String name;
    public Person(int id, String name)
    {
        this.id = id;
        this.name = name;
    }
    public String toString()
    {
        return "Person: " + id + " " + name;
    }
}

(2)序列化功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerialTest
{
    public static void main(String[] args) throws IOException
    {
        Person person = new Person(1234, "wang");
        System.out.println("Person Serial" + person);
        FileOutputStream fos = new FileOutputStream("Person.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(person);
        oos.flush();
        oos.close();
    }
}

(3)反序列化功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeserialTest
{
    public static void main(String[] args) throws IOException, ClassNotFoundException
    {
        Person person;
        FileInputStream fis = new FileInputStream("Person.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        person = (Person) ois.readObject();
        ois.close();
        System.out.println("Person Deserial" + person);
    }
}

情况一:假设Person类序列化之后,从A端传输到B端,然后在B端进行反序列化。在序列化Person和反序列化Person的时候,A端和B端都需要存在一个相同的类。如果两处的serialVersionUID不一致,会产生什么错误呢?
【答案】可以利用上面的代码做个试验来验证:
先执行测试类SerialTest,生成序列化文件,代表A端序列化后的文件,然后修改serialVersion值,再执行测试类DeserialTest,代表B端使用不同serialVersion的类去反序列化,结果报错:
Exception in thread "main" java.io.InvalidClassException: test.Person; local class incompatible: stream classdesc serialVersionUID = 1234567890, local class serialVersionUID = 123456789
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:560)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1580)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1493)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1729)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1326)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
    at test.DeserialTest.main(DeserialTest.java:15)
    
情况二:假设两处serialVersionUID一致,如果A端增加一个字段,然后序列化,而B端不变,然后反序列化,会是什么情况呢?
【答案】新增 public int age; 执行SerialTest,生成序列化文件,代表A端。删除 public int age,反序列化,代表B端,最后的结果为:执行序列化,反序列化正常,但是A端增加的字段丢失(被B端忽略)。

情况三:假设两处serialVersionUID一致,如果B端减少一个字段,A端不变,会是什么情况呢?
【答案】序列化,反序列化正常,B端字段少于A端,A端多的字段值丢失(被B端忽略)。

情况四:假设两处serialVersionUID一致,如果B端增加一个字段,A端不变,会是什么情况呢?
验证过程如下:
先执行SerialTest,然后在实体类Person增加一个字段age,如下所示,再执行测试类DeserialTest.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

import java.io.Serializable;
public class Person implements Serializable
{
    private static final long serialVersionUID = 123456789L;
    public int id;
    public String name;
    public int age;
    public Person(int id, String name)
    {
        this.id = id;
        this.name = name;
    }
    public String toString()
    {
        return "Person: " + id + " " + name;
    }
}

相应的修改测试类DeserialTest,打印出age的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerialTest
{
    public static void main(String[] args) throws IOException
    {
        Person person = new Person(1234, "wang");
        System.out.println("Person Serial" + person + " age:" + person.age);
        FileOutputStream fos = new FileOutputStream("Person.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(person);
        oos.flush();
        oos.close();
    }
}

结果为:
Person Deserial Person: 1234 wang age: 0
说明序列化,反序列化正常,B端新增加的int字段被赋予了默认值0。
最后通过下面的图片,总结一下上面的几种情况。

转载于:https://www.cnblogs.com/hubavyn/p/7150913.html

serialVersionUID的作用(转)相关推荐

  1. java 四字节uid,Java入门教程-序列化版本号serialVersionUID的作用

    原标题:Java入门教程-序列化版本号serialVersionUID的作用 Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象.序列化是Java中实现持久化存储的一种方法 ...

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

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

  3. java 序列化版本号_序列化版本号serialVersionUID的作用

    原标题:序列化版本号serialVersionUID的作用 Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象.序列化是Java中实现持久化存储的一种方法:为数据传输提供了 ...

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

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

  5. serialversionuid的作用_为什么阿里Java规约要求谨慎修改serialVersionUID字段

    serialVersionUID简要介绍 serialVersionUID是在Java序列化.反序列化对象时起作用的一个字段.Java的序列化机制是通过判断类的serialVersionUID来验证版 ...

  6. java_version干什么的_java类中serialVersionUID的作用及其使用

    实现Serializable接口的目的是为类可持久化,比如在网络传输或本地存储,为系统的分布和异构部署提供先决条件.若没有序列化,现在我们所熟悉的远程调用,对象数据库都不可能存在, serialVer ...

  7. 关于serialVersionUID的作用解释说明

    文章目录 1.这是什么? 2.如果不使用会发生什么? 3.代码结合讲解 3.1不设置serialVersionUID时正常序列化和反序列化 3.2 类增加字段后进行反序列化? 3.3手动设置seria ...

  8. 序列化的高阶认识-serialVersionUID的作用

    在IDEA中通过如下设置可以生成serializeid 字面意思上是序列化的版本号,凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量 演示步骤 1. 先将user对象序列 ...

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

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

最新文章

  1. CVPR2020:三维点云无监督表示学习的全局局部双向推理
  2. JavaScript四(DOM编程)
  3. Asp.net常用技巧
  4. python进程\协程\异步IO
  5. Netty入门(二)时间服务器及客户端
  6. 如何设置jquery的ajax方法为同步
  7. rosweb显示2d地图时,车在地图中的图形显示有时后特别大
  8. php post提交 java接收,asp如何接收php或java提交post过来的json数据
  9. Beego 框架学习(一)
  10. 自动驾驶操作系统现状与发展趋势
  11. 怎样用等价类划分设计测试用例
  12. z3735 android5.1,『Sanghua的暴力美学』intel Z3735e 昂达V819i完全拆解。
  13. 『常识』罗胖的《罗辑思维》中推荐的书 — 未校正
  14. 最全汇总GAN网络及其各种变体(附论文及代码实现)
  15. 计算机硬盘图标闪烁,电脑本地磁盘图标显示异常如何解决
  16. python基础-猜数字游戏
  17. 第一节:Ajax 入门及环境
  18. eclipse打不开的问题
  19. 期权和期货的定义及区别
  20. 一年的第多少周+一个月的第多少天+一周的第多少天

热门文章

  1. Python 微信机器人:itchat库识别消息来源于群聊还是个人
  2. python pandas爬取网页成绩表格,计算各个类别学分
  3. Python 小把戏之下载小说
  4. 结构对齐--__packed与#pragma pack
  5. [YTU]_2577( 小数计算——结构体)
  6. Python中文问题 或 SyntaxError: Non-ASCII character '\xe8' in file
  7. OpenCV函数 Canny 检测边缘
  8. 更改Cmd默认默认路径(以设置为D:/为例)
  9. PAT Basic 1032
  10. webpack4.0 babel配置遇到的问题