serialVersionUID的作用

对于实现了Serializable接口的类,如果没有主动在程序中加上serialVersionUID,那么编译器会默认加上。一般情况下最好是自己加上,编译器默认的ID依赖于编译器的实现,在反序列化时,可能会报InvalidClassExceptions

先看java bean的代码:

 1 package com.oppo.test;
 2 
 3 import java.io.Serializable;
 4 
 5 public class Student implements Serializable {
 6 
 7     /**
 8      * 
 9      */
10     private static final long serialVersionUID = 1L;
11     private int id;
12 
13     public int getId() {
14         return id;
15     }
16 
17     public void setId(int id) {
18         this.id = id;
19     }
20 }

序列化的工具类:

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.FileOutputStream;
 4 import java.io.ObjectInputStream;
 5 import java.io.ObjectOutputStream;
 6 
 7 public class UIDTester {
 8 
 9     /**
10      * @param args
11      */
12     public static void main(String[] args) throws Exception{
13         // TODO Auto-generated method stub
14 
15         File file = new File("out.ser");
16         FileOutputStream fos = new FileOutputStream(file);
17         ObjectOutputStream oos = new ObjectOutputStream(fos);
18         
19         SerializeMe serializeMe = new SerializeMe(1);
20         oos.writeObject(serializeMe);
21         
22         FileInputStream fis = new FileInputStream(file);
23         ObjectInputStream ois = new ObjectInputStream(fis);
24         
25         Student s = (Student)ois.readObject();
26         
27         System.out.println("id: " + s.getId());
28         ois.close();
29     }
30 
31 }

显然,这段代码是对Student类的序列化和反序列化。在Student类中,添加了序列化ID serialVersionUID,需要注意的是,虽然序列化的时候并不会序列化类中的静态成员和临时成员,但对serialVersionUID是个例外,序列化时serialVersionUID会被写到输出流中,运行程序,有如下输出:

id: 1

不要删除输出文件,改变Student类中的serialVersionUID

private static final long serialVersionUID = 2L;

然后将UIDTester类中对Student类的序列化步骤注释掉,即只进行反序列化工作,运行程序:

Exception in thread "main" java.io.InvalidClassException:

程序报异常了,因为序列化是ObjectOutputStream将serialVersionUID写到文件out.ser(其实也可能写到socket中登登)中,此时为1L,在反序列化时ObjectInputStream从文件中读出serialVersionUID,发现这个UID和当前类Student版本的UID不一致,就会扔出InvalidClassException异常。

如果对类A进行序列化后,反序列化工作在网络的另一端(算得上是空间距离吧,这时候可能JVM的版本都不相同)或者时隔很久以后(算是时间距离),那么在这个距离段内,类A的成员可能会发生变化(这个真心谁也说不准),需要有一套版本机制,于是serialVersionUID应运而生。它总是检查输出流和输入流里面的对象版本是否改变了。所以,一旦Student类有所改变,我们都有责任改变它的serialVersionUID,如果不变,反序列化之后根本得不到新增的成员变量。

对于Externalizable,详情 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4094702

posted @ 2012-12-20 20:01  leealways87  阅读(514)  评论(0编辑  收藏  举报