http://www.cnblogs.com/guanghuiqq/archive/2012/07/18/2597036.html

简单来说,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,类型为long的变量时,Java序列化机制会根据编译的class(它通过类名,方法名等诸多因素经过计算而得,理论上是一一映射的关系,也就是唯一的)自动生成一个serialVersionUID作序列化版本比较用,这种情况下,如果class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释,等等),就算再编译多次,serialVersionUID也不会变化的.

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

如果你没有考虑到兼容性问题时,就把它关掉,不过有这个功能是好的,只要任何类别实现了Serializable这个接口的话,如果没有加入 serialVersionUID,Eclipse都会给你warning提示,这个serialVersionUID为了让该类别 Serializable向后兼容。

问题一:假设有A端和B端,如果2处的serialVersionUID不一致,会产生什么错误呢?

问题二:假设2处serialVersionUID一致,如果A端增加一个字段,B端不变,会是什么情况呢?

问题三:假设2处serialVersionUID一致,如果B段增加一个字段,A端不变,会是什么情况呢?

问题四:假设2处serialVersionUID一致,如果A端减少一个字段,B端不变,会是什么情况呢?

问题五:假设2处serialVersionUID一致,如果B端减少一个字段,A端不变,会是什么情况呢?

例子如下:写2个类,类名相同,字段相同,方法相同.放在不同的包里,来模仿A端和B端.

实体类:在本例中,在测试类SerialTest执行前代表A端,然后,在测试类DeserialTest执行前代表B端.

import java.io.Serializable;

public class Serial implements Serializable{
private static final long serialVersionUID = -3203784146884841661L; /** * */ int id;
String name; public Serial(int id, String name) {
this.id = id;
this.name = name;
} public String toString() {
return "DATA: " + id + " " +name;
}
}

测试类,代表A端的序列化:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream; public class SerialTestA {
/** * @param args */
public static void main(String[] args) {
// TODO Auto-generated method stub
Serial serial1 = new Serial(1,"song");
System.out.println("Object Serial"+serial1);
try {
FileOutputStream fos = new FileOutputStream("serialTest.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(serial1);
oos.flush();
oos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

测试类,代表B端的反序列化:

问题一:假设有A端和B端,如果2处的serialVersionUID不一致,会产生什么错误呢?

答案如下:

1)先执行测试类SerialTest,然后修改serialVersion值(或注释掉serialVersion并编译),再执行测试类DeserialTest,报错:

java.io.InvalidClassException: com.test.serializable.Serial; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 11

2)A端和B端都没显示的写serialVersionUID,实体类没有改动(如果class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释,等等),).序列化,反序列化正常.

问题二:假设2处serialVersionUID一致,如果A端增加一个字段,B端不变,会是什么情况呢?

答案二: 序列化,反序列化正常,A端增加的字段丢失(被B端忽略).

问题五:假设2处serialVersionUID一致,如果B端减少一个字段,A端不变,会是什么情况呢?

答案:与问题二类似,序列化,反序列化正常,B端字段少于A端,A端多的字段值丢失(被B端忽略).

问题三:假设2处serialVersionUID一致,如果B段增加一个字段,A端不变,会是什么情况呢?

问题四:假设2处serialVersionUID一致,如果A端减少一个字段,B端不变,会是什么情况呢?(与问题三类似,四答案:序列化,反序列化正常,B端字段多余A端,B端多出的字段被赋予对应类型的默认值)

答案三: 序列化,反序列化正常,B端新增加的int字段被赋予了默认值0.

例子如下:

3)先执行SerialTest,然后在实体类增加一个字段age,再执行测试类DeserialTest.

package com.test.serializable;

import java.io.Serializable;

public class Serial implements Serializable {

/**   *   */ private static final long serialVersionUID = -2337937881709830076L;

/**   *   */ //private static final long serialVersionUID = 1L; int id;

String name;       public Serial(int id, String name) {           this.id = id;           this.name = name;       }       public String toString() {           return "DATA: " + id + " " +name;         }     public int age ;//在B端增加一个新字段 }

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

package com.test.serializable;

import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream;

public class DeserialTest {

/**   * @param args   */ public static void main(String[] args) {   // TODO Auto-generated method stub   Serial serial2 ;   try {    FileInputStream fis = new FileInputStream("serialTest.txt");    ObjectInputStream ois = new ObjectInputStream(fis);    serial2 = (Serial)ois.readObject();    ois.close();    System.out.println("Object Deserial"+serial2+" age="+serial2.age);   } catch (FileNotFoundException e) {    // TODO Auto-generated catch block    e.printStackTrace();   } catch (IOException e) {    // TODO Auto-generated catch block    e.printStackTrace();   } catch (ClassNotFoundException e) {    // TODO Auto-generated catch block    e.printStackTrace();   }   }

}

打印结果如下:

Object DeserialDATA: 1 song age=0

说明序列化,反序列化正常,B端新增加的int字段被赋予了默认值0.

上面的情况对增加/减少 字段/方法 都适用.

//但当serialVersionUID相同时,它就会将不一样的field以type的预设值Deserialize,可避开不兼容性问题。

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

  1. serialVersionUID的作用 (zz)

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

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

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

  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 ...

随机推荐

  1. Java 8手动实现一个Collector

    我们看一下Stream中的collect的方法. collect(toList())方法由Stream里的值生成一个列表,是一个及早求值的操作. Stream的of方法使用一个初始值生成新的Strea ...

  2. MQTT在平台中的应用【本文摘自智车芯官网】

    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协议支持所有平台,几乎可以把所有联 ...

  3. Apache服务器的Options 的 Indexes FollowSymLinks详解

    禁止显示Apache目录列表 - Indexes FollowSymLinks 如何修改目录的配置以禁止显示 Apache 目录列表. 缺省情况下如果你在浏览器输入地址: http://localho ...

  4. 算法(12)Best Time to Buy and Sell Stock II

    题目:最大收益 [1,2,3,9,2,3] 思路:这道题竟然是easy的?! 最终的解法非常简单,只要把单个波峰减去波谷就可以了,比如在上面的例子中[1-2-3-9][2-3]这就是单个波峰波谷!为什 ...

  5. 算法(2) Find All Numbers Disappeared in an Array

    题目:整数数组满足1<=a[i]<=n(n是数组的长度),某些元素出现一次,某些元素出现两次,在数组a[i]中找到[1,n]区间中未出现的数字.比如输入[4,3,2,7,8,2,3,1], ...

  6. 批处理中的IF详解

    在CMD使用IF /?打开IF的系统帮助会发现IF有3种基本的用法! 第一种用法:IF [NOT] ERRORLEVEL number command 这种用法现在很少用了,因为它需要使用到CHOIC ...

  7. 如何用Ajax传一个数组数据

    PHP接收多个同名复选框信息不像ASP那样自动转换成为数组,这给使用带来了一定不便.但是还是有解决办法的,就是利用javascript做一下预处 理.多个同名复选框在javascript中还是以数组的 ...

  8. VK Cup 2016 - Round 1 (Div. 2 Edition) A Bear and Reverse Radewoosh

    A. Bear and Reverse Radewoosh time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  9. Codeforces Round #526 (Div. 2) A.B

    A. The Fair Nut and Elevator 题目链接:https://codeforces.com/contest/1084/problem/A 题意: 一栋房子有n层楼,同时有个电梯( ...

  10. c++编辑器下载地址

    https://msdn.itellyou.cn/ 输入上述地址选中下图所示的按钮: