对象序列化为何要定义serialversionuid的来龙去脉 -pg电子游戏网站

`
lenjey
  • 浏览: 89495 次
  • 性别:
  • 来自: 北京
博主相关
  • 博客
  • 微博
  • 相册
  • 收藏
  • 社区版块
    • ( 0)
    • ( 44)
    • ( 0)
    存档分类

    对象序列化为何要定义serialversionuid的来龙去脉

      博客分类:
    • j2se
    在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是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;
    分享到:
    评论
    5 楼 g_man1990 2017-04-06  
    serialversionuid可以继承么?
    4 楼 timjames 2017-03-03  
      学习了!
    3 楼 liu5840779 2014-10-22  
    给力的楼主
    2 楼 xunke515 2014-03-31  
    例子不错。 顶个。
    顺便问下“因此,只要我们自己指定了serialversionuid,就可以在序列化后,去添加一个字段”
    这个字段在后期还原之后的值是什么,默认值么?比如说int的默认值是0
    1 楼 gdgzczh 2011-10-26  
          
    学习了,很奇妙

    相关推荐

      代码中,我们定义了一个 person 类,...需要注意的是,序列化和反序列化的类必须具有相同的 serialversionuid,以确保对象的一致性。同时,为了避免序列化敏感信息,可以使用 transient 关键字标记不需要序列化的字段。

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

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

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

      1. 先将 user 对象序列化到文件中 2. 然后修改 user 对象,增加 serialversionuid 字段 3. 然后通过反序列化来把对象提取出来

      反序列化:将二进制流恢复为数据对象称之为反序列化(deserialization) 序列化方式 java原生序列化 java类通过实现serializable接口实现该类对象的序列化。java序列化保留了对象类的元数据(类、继承类等),以及对象...

      java中serialversionuid的解释,对于版本的说明解释问题

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

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

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

      本篇文章主要介绍了详述intellij idea 中自动生成 serialversionuid 的方法(图文),具有一定的参考价值,感兴趣的小伙伴们可以参考一下。

      三期第一张io笔记 6

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

      当尝试在不同版本的类之间进行序列化时,java 的内置序列化不足。 使用静态 ... 如果您想要解决 java 序列化问题,那就别无所求! stephenerialization 使您可以轻松地在不同版本的 java 类之间进行序列化!

      以下是对java中的serialversionuid进行了全面的分析介绍。需要的朋友可以过来参考下

      全面解析了java中serialversionuid的作用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

      描述:类是可序列化的,但是没有定义serialversionuid; 处理方式:自动生成serialversionuid; field only ever set to null 描述:field一直被设置为null; 处理方式:检查相关filed的调用情况,看所有对field的...

      主要介绍了idea如何自动生成serialversionuid,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

      null 博文链接:https://jnh.iteye.com/blog/1300193

    global site tag (gtag.js) - google analytics
    网站地图