`
hthjava
  • 浏览: 29510 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

java中序列化serialVersionUID

    博客分类:
  • java
阅读更多
原文地址http://www.crabone.com/index.php/2009/05/05/286.html

在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是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;
分享到:
评论
1 楼 skying007 2011-01-18  
文章分析的很到位,拜读了。

相关推荐

    什么是Java的序列化和反序列化?如何实现对象的序列化和反序列化?(java面试题附答案).txt

    通过实现 Serializable 接口,Java对象可以被序列化和反序列化。序列化可以将对象转换为字节流,以便于存储或传输。反序列化则可以将字节流重新转换为原始对象。需要注意的是,序列化和反序列化的类必须具有相同的 ...

    序列化版本号serialVersionUID的作用_动力节点Java学院整理

    序列化版本号serialVersionUID的作用_动力节点Java学院整理.

    java序列化和serialVersionUID的使用方法实例

    主要介绍了java序列化和serialVersionUID的使用方法实例的相关资料,这里说明很详细的使用方法让你彻底学会,需要的朋友可以参考下

    java序列化实现演示

    Java序列化机制(2)- serialVersionUID 实验 http://blog.csdn.net/suileisl/article/details/16991753

    3分钟读阿里Java手册: 序列化

    前言 下面这句代码,相信大家可能跟我一样都非常熟悉,但是真正了解的人又有多少呢? private static final long serialVersionUID = 1L;...Java序列化保留了对象类的元数据(类、继承类等),以及对象数据,兼容性好

    序列化和反序列化1

    序列化ID 两个类的序列化ID相同才能保证反序列的对象是一致private static final long serialVersionUID在序列化过程中,

    JAVA基础,常见java基础问题.rar

    反序列化就是序列化的逆过程,把磁盘文件中或网络节点的二进制数据恢复成java对象的过程,通常是将二进制数据转换为对象。 序列化的应用场景:将对象存储在文件或数据库中,利用套接字在网络上进行对象传输,RMI...

    从根上读懂阿里手册 | 为啥不能轻易修改serialVersionUID字段

    阿里巴巴开发手册,(四)OOP 规约,第 13 条解释如下: 【强制】序列化类新增属性时,请...首先我们需要了解一下序列化,我们可以简单了理解序列化就是把 Java 对象转换成另一种形态的数据,这种形态的数据可以用于

    Stephenerialization:Java 跨版本序列化问题的解决方案。-开源

    当尝试在不同版本的类之间进行序列化时,Java 的内置序列化不足。 使用静态 serialVersionUID 是一个好的开始,但还不够。 如果您想要解决 Java 序列化问题,那就别无所求! Stephenerialization 使您可以轻松地在...

    java8集合源码-Java:Java

    Java中序列化和反序列化的区别。 什么是SerialVersionUID? 内部类和子类的区别。 JSON 相对于 XML 的优势是什么? 我们可以两次导入相同的包/类吗? JVM 会在运行时加载包两次吗? 静态加载和动态类加载的区别? ...

    Serializable-master.zip

    1.serialVersionUID-->适用于Java的序列化机制: 2.具体化序列化过程: 3.serialVersionUID有两种显示的生成方式:

    Java关键字—-transient

    本篇文章序列化、反序列化用的类是同一个类,可以通过注释main中1然后修改Stu类实现有无transient关键字修饰、serialVersionUID是否不同,得到以下结果: 1、serialVersionUID的数值大小不会影响序列化后的字节数...

    java-lt:关于flink的一些测试

    idea 设置 java 类无序列化 id 警告 File--> Settings--> Editor--> Inspections--> Java--> Serialization issues--> 将 Serializable class without serialVersionUID 勾选 idea jihuoma #ssh ...

    阿里巴巴编码规范 基础技能认证 考题分析(考题+答案).docx

    D .POJO类的serialVersionUID不一致会抛出序列化运行时异常。 多选 9.关于Java的接口描述,下列哪些说法符合《阿里巴巴Java开发手册》:BCD A .在接口类中的方法和属性使用public修饰符。 B .对于Service类,...

    memcached1

    我们首先把TBean的一个实例放入缓存中,然后再取出来,并进行名称的修改,然后我们再取这个对象,我们再看其名称,发现修改的对象并不是缓存中的对象,而是通过序列化过来的一个实例对象,这样我们就无须担心对原生...

    SerialVer task for ANT-开源

    SerialVer将Java serialver功能添加到Apache-Jakarta的ANT工具中。 该项目在可序列化类的源代码中添加了Tasks和FilterReaders来获取,插入和修改serialVersionUID。

    @SuppressWarnings

    serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告。 finally 任何 finally 子句不能正常完成时的警告。 all 关于以上所有情况的警告。 @SuppressWarnings 批注允许您选择性地取消特定代码段(即,类或...

    基于Spring的HttpInvoker实现改写egova_invoker.zip

    ProxyFactory.proxy 方法,生成接口的代理对象,直接调用方法客户端和服务器端的接口和实体类要一致,实体类必须是可以序列化的比如:定义Bean: public class DemoBean implements java.io.Serializable{ ...

Global site tag (gtag.js) - Google Analytics