声明: 关于序列化/反序列化 这有一篇javaeye中很全面的解释: 浏览. 本文主要记录我对平台中的序列化/反序列化的理解学习. 由于个人文采有限, 表达,组织不合适, 及粘贴代码不完整, 望见谅
在平台中在自定义异常类中,看到有 private static final long serialVersionUID = -7564015249480613950L;
这行代码, 有几个疑问:
1. 这行代码作用是什么? 不加有怎样?
网上搜了一下大体知道,这是个序列化和返序列化版本版本控制的标志.对于所用实现java.lang.Serializable接口的类都建议使用.(关于序列化和反序列化见 3 )
测试1: 不添加序列化
//private static final long serialVersionUID = 5159342088681301L;
使用jdk1.5 编译,序列化产生对象文件.
使用jdk1.6 反序列获得对象,可以获得对象的属性.
?问题1 并没有报错,说版本不同? =>已解决
:是我对此理解还有问题?
在http://www.blogjava.net/invisibletank/archive/2007/11/15/160684.html
"如果你的类Serialized存到硬盘上面后,可是后来你却更改了类别的field(增加或减少或改名),当你Deserialize时,就会出现Exception的,这样就会造成不兼容性的问题。 "
测试2:
先序列化一个对象, 然后在类中增加一个成员变量 short shortVar = 0;
然后调用反序列化方法, 结果:
java.io.InvalidClassException: com.bryant.test.SerialTest; local class incompatible: stream classdesc serialVersionUID = 659456840250255615, local class serialVersionUID = -7474528909570989615 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:546)
符合预测,即没有写serialVersionUID时,版本不同报错.
测试3 : 添加版本控制,
先序列化对象, 然后删除一个成员变量 short shortVar = 0; 进行反序列化,
运行正常.
至此问题1解决.
总结: 在一个可以序列化类中,加入serialVersionUID可以保持版本兼容:(避免 当序列化一个对象后,然后增减类成员变量,再进行反序列化时 程序出异常)
2. 这个代码变量的值是怎么获得的?
在eclipse中当类实现Serrial接口时,eclipse会在类所在行叹号提示,
"The serializable class SerialTest does not declare a static final serialVersionUID field of type
long ", ctrl + 1 : 点击"add default serial version Id" ,自动生成
private static final long serialVersionUID = 1L;
点击"add generated serial version Id " ,生成
private static final long serialVersionUID = 8515159342088681301L;
解决.
问题2 ,default和 generated Id 区别?
3. 序列化/反序列化
序列化: 把java对象生成一个文件(这些文件包含对象的所有信息)
反序列化: 把序列化生成的文件 转化成java对象
怎么序列化/反序列化一个对象?
3.1 序列化步骤
创建文件对象(所有序列化对象生成的文件) ->封装成Inputstream流 -> 封装成ObjectOutputStream对象oos
通过调用oos的writeObject()方法,输出序列化对象.
public static void serialObj(Object obj) throws IOException{ File file = new File("c:\\", obj.toString() ); ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(new FileOutputStream(file)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); throw e; } //create output stream try { oos.writeObject(obj); } catch (IOException e) { // TODO Auto-generated catch block logger.error("servial error!"); e.printStackTrace(); }finally{ oos.close(); } logger.info("servial ok!"); }
3.2 反序列化步骤
创建文件对象 --> 封装成inputstream流 --> 封装成ObjectinputStream流对象ois
调用ois的readObject() 方法返回对象,
强制类型转换成已知类型的对象.
public void getSerivalObj() throws FileNotFoundException, IOException, ClassNotFoundException{ PropertyConfigurator.configure("D:/workspace/common_jars/log4j.properties"); File file = new File("c:\\", String.valueOf( "com.bryant.test.SerialTest@1270b73" ) ); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); Object obj = ois.readObject(); logger.info( ((SerialTest)obj).intTest + ((SerialTest)obj).s ); }