在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到内存,等要用了,再还原到对象中,说白了,就是能将一个2进制文件变成内存中的对象。在JAVA中,要实现这种机制,只要实现Serializable接口就可以了,先看下面这个简单例子,serialVersionUID稍后引出。我们先定义一个简单的Person类,然后创建这个对象,最后序列化它到一个文件。

import java.io.Serializable;

public class Person implements Serializable {

    private String name;

    public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; public class WhySerialversionUID { public static void main(String[] args) throws Exception { //这里是把对象序列化到文件
Person crab = new Person();
crab.setName("Mr.Crab"); ObjectOutputStream oo = new ObjectOutputStream
(new FileOutputStream("crab_file"));
oo.writeObject(crab);
oo.close(); //这里是把对象序列化到文件,我们先注释掉,一会儿用
//ObjectInputStream oi = new ObjectInputStream
// (new FileInputStream("crab_file"));
//Person crab_back = (Person) oi.readObject();
//System.out.println("Hi, My name is " + crab_back.getName());
//oi.close(); }
}

运行完后,我们发现有了一个crab_file文件,这个文件就保存这crab对象在内存中的形态。同样,我们把这部分代码注释掉,运行下面那段还原代码,发现,crab_file文件可以被转化为一个对象。

一切都那么顺利,但是如果在序列化之后,Person这个类发生了改变呢?比如,多了一个成员变量。我们做如下试验,还是先将对象序列化到一个文件中,之后在Person这个类中添加一个成员变量,如下:

import java.io.Serializable;

public class Person implements Serializable {

    private String name;
//添加这么一个成员变量
private String address; public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

之后,我们再去运行一下还原,就发现运行出错了,会报如下错误: 
Exception in thread “main” java.io.InvalidClassException: Person; local class incompatible: stream classdesc serialVersionUID = 8383901821872620925, local class serialVersionUID = -763618247875550322 
意思就是说,文件流中的class和classpath中的class,也就是修改过后的class,不兼容了,处于安全机制考虑,程序抛出了错误,并且拒绝载入。那么如果我们真的有需求要在序列化后添加一个字段或者方法呢?应该怎么办?那就是自己去指定serialVersionUID。之前,在我们的例子中,我们是没有指定serialVersionUID的,那么java编译器会自动给这个class进行一个摘要算法,类似于指纹算法,只要这个文件多一个空格,得到的UID就会截然不同的,可以保证在这么多类中,这个编号是唯一的。所以,我们添加了一个字段后,由于没有显指定serialVersionUID,编译器又为我们生成了一个UID,当然和前面保存在文件中的那个不会一样了,于是就出现了2个号码不一致的错误。因此,只要我们自己指定了serialVersionUID,就可以在序列化后,去添加一个字段,或者方法,而不会影响到后期的还原,还原后的对象照样可以使用,而且还多了方法可以用,呵呵。但是serialVersionUID我们怎么去生成呢?你可以写1,也可以写2,都无所谓,但是最好还是按照摘要算法,生成一个惟一的指纹数字,eclipse可以自动生成的,jdk也自带了这个工具。一般写法类似于 
private static final long serialVersionUID = -763618247875550322L;

注:本文摘自http://lenjey.iteye.com/blog/513736

最新文章

  1. 实现SQL Server 2008 Reporting Services匿名访问报表有两种方法
  2. dp水题 序列问题 (9道)
  3. Android向系统相册中插入图片,相册中会出现两张 一样的图片(只是图片大小不一致)
  4. 20145215《Java程序设计》第10周学习总结
  5. magento 图片缓存是如何生成的
  6. 1191: [HNOI2006]超级英雄Hero - BZOJ
  7. 18.java.lang.OutOfMemoryException
  8. nyoj-709-异形卵(水题)
  9. OC-多线程安全隐患及一般解决办法
  10. NSDictionary 总结 -iOS
  11. linux学习(JDK,Tomcat,nginx)安装
  12. JS-函数作用域
  13. json转换字符串
  14. sqlserver触发器insert,delete,update
  15. keil mdk5安装
  16. Java反射获取对象VO的属性值(通过Getter方法)
  17. mysql事务隔离级别设置
  18. .net访问Oracle数据库
  19. 在启动mysql的时候出现如下问题:“ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)”
  20. Mysql:主从集群配置

热门文章

  1. java udp 广播
  2. Android资源文件 - 使用资源存储字符串 颜色 尺寸 整型 布尔值 数组
  3. java appium客户端 6.1.0android长按及滑动变更
  4. MySql(十六):MySql架构设计——MySQL Cluster
  5. LeetCode OJ 之 Maximal Square (最大的正方形)
  6. iOS7.0中UILabel高度调整注意事项
  7. iOS7相机隐私判断
  8. 有关https安全的相关内容介绍
  9. docker 安装MySQL远程连接
  10. kvm 给虚机增加网卡