本文系转载,原文链接: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。
最后通过下面的图片,总结一下上面的几种情况。

serialVersionUID的作用(转)的更多相关文章

  1. serialVersionUID, ObjectInputStream与ObjectOutputStream类,Serializable接口,serialVersionUID的作用和用法

    ObjectInputStream与ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入 Ser ...

  2. serialVersionUID的作用 (zz)

    serialVersionUID的作用 2011-05-12 16:04:19|  分类: java|举报|字号 订阅     在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘 ...

  3. serialVersionUID的作用以及设置方法(转)

    声明:本篇文章是转载的 http://blog.csdn.net/kakaxi_77/article/details/8129070 http://snowlotus.iteye.com/blog/2 ...

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

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

  5. 序列化与反序列化中serialVersionUID的作用(通俗易懂)

    serialVersionUID:字面意思上是序列化的版本号,这个在刚刚接触java编程时,学序列化大家一般都不会注意到,在你一个类序列化后除非你强制去掉了myeclipse中warning的功能,在 ...

  6. serialVersionUID的作用以及IDEA、Eclipse如何自动生成serialVersionUID

    说到serialVersionUID,首先要讲讲序列化. 序列化: 序列化可以将一个java对象以二进制流的方式在网络中传输并且可以被持久化到数据库.文件系统中,反序列化则是可以把之前持久化在数据库或 ...

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

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

  8. 【Struts中private static final long serialVersionUID的作用】

     private static final long serialVersionUID = -1672970955045193907L;   SerialVersionUID,后面简称SUID 其实序 ...

  9. serialVersionUID的作用

    Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的.在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的seri ...

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

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

随机推荐

  1. 【刷题】洛谷 P4143 采集矿石

    题目背景 ZRQ成功从坍塌的洞穴中逃了出来.终于,他看到了要研究的矿石.他想挑一些带回去完成任务. 题目来源:Zhang_RQ哦对了ZRQ就他,嗯 题目描述 ZRQ发现这里有 \(N\) 块排成一排的 ...

  2. Alpha 冲刺 —— 十分之二

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助前端界面的开发 搭建测试用服务器的环境 完成 ...

  3. 后渗透提权辅助工具BeRoot详解

    0x00 工具介绍 前言 BeRoot是一个后期开发工具,用于检查常见的Windows的配置错误,以方便找到提高我们提权的方法.其二进制编译地址为: https://github.com/Alessa ...

  4. excel换行

    在excel的单元格中换行 1. windows alt + enter 2. mac command + alt + enter

  5. Centos 下 error while loading shared libraries: libopencv_core.so.3.0

    error while loading shared libraries: libopencv_core.so.3.0 Check if those libraries are present in ...

  6. js浏览器调试方法

    chrome浏览器可在需要断点的地方写一个关键字 "debugger",这样在 js 运行到这里的时候会停止继续运行,并可以查看当前状态

  7. gflag使用

    #include <gflags/gflags.h> #include <iostream> // 声明全局flag DEFINE_bool(my_bool, false, & ...

  8. [机器学习]-PCA数据降维:从代码到原理的深入解析

    &*&:2017/6/16update,最近几天发现阅读这篇文章的朋友比较多,自己阅读发现,部分内容出现了问题,进行了更新. 一.什么是PCA:摘用一下百度百科的解释 PCA(Prin ...

  9. 巧用Java中Calendar工具类

    Java的JDK中提供了一系列好用的util工具类.Calendar就是java.util中用于处理日期的工具类.且该工具类易学易用实用. 工具类Calendar是抽象类. PS:为什么把Calend ...

  10. 第5章-Vue.js交互及生命周期练习

    一.学习目标 使用网络请求进行前后端交互 (重点) 理解钩子函数的作用  (难点) 掌握Vue.js过滤器的使用方法 了解Vue.js事件的深入用法  (重点) 二.仿写留言板 2.1.实现" ...