zoukankan      html  css  js  c++  java
  • serialVersionUID的作用

     

           在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,

    当有10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,

    再把保存在硬盘中的对象还原到内存中,说白了,就是能将一个2进制文件变成内存中的对象。在JAVA中,要实现这种机制,只要实现Serializable接口

    就可以了,先看下面这个简单例子,serialVersionUID稍后引出。我们先定义一个简单的Person类,然后创建这个对象,最后序列化它到一个文件。

     

    /*****(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.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class WhySerialversionUID { public static void main(String[] args) throws Exception {   Person person= new Person();   person.setName("jack");   ObjectOutputStream oo = new ObjectOutputStream (new FileOutputStream(new File("E://jack.test")));   oo.writeObject(person);   oo.close(); }
    /*****(通过以下方法可以正常的将文件中保存的对象还原到内存中)*******/ import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream;
    public class WhySerialversionUID { public static void main(String[] args) throws Exception {

      ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E://jack.test")));   Person person = (Person)ois.readObject();   String name= person.getName();   System.Out.Print("name is: "+name);
    }

     

    一切都那么顺利,但是如果在序列化之后,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;

    在引用serializable这个类的前面有一个感叹号,单击这个感叹号后会有提示,一个是默认的,一个为此类自动产生一个SerialVersionUID!

     

     

     

  • 相关阅读:
    JNI实例(含代码)
    sizeof()小结
    【转】C++ 关键字——friend
    curl资料小结
    【Curl (libcurl) 开发 之一】Cocos2dx之libcurl(curl_easy)的编程教程(帮助手册)!
    JSP中统一错误信息输出
    在号码池取连续号码的算法
    常用的文件操作方法
    走出基金净值的误区
    ResultSet概论
  • 原文地址:https://www.cnblogs.com/mingyue1818/p/4042893.html
Copyright © 2011-2022 走看看