购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

陷阱14

不同版本
——反序列化对象

在编程的过程中,为了数据的安全,可以使用文件存储数据对象,这样,当需要从文件中读取数据对象时,如果对象的版本不一致,程序将无法从文件中读取数据对象,从而可以有效地保证数据的安全。

在Java中提供了一个java.io.Serializable接口,该接口中没有任何方法,序列化类只需要实现这个接口即可,为了保证对象序列化的版本一致,可以通过在序列化类中定义属性serialVersionUID来实现。

serialVersionUID属性的定义格式如下:

说 明

上面代码中的长整型常量可以为任意的长整型数值,如 200L,只要为该类指定了属性serialVersionUID,并为其指定了具体的长整型数值,这样,当序列化类的属性发生改变时,就可以保证序列化对象的版本一致了,只有对象的版本一致才能被成功地反序列化。

接下来通过一个实例来说明,序列化对象时为什么要使用serialVersionUID属性来指定对象的版本。

例3.14 创建3个类,分别序列化类、将序列化对象保存到文件中的类和从文件中读取序列化对象的类,目的是测试对象序列化的版本对反序列化的影响。(光盘位置:光盘\MR\Instance\3\14\ UnserialObject)。

1)序列化类Student

说 明

上面的代码创建了一个实现了Serializable接口的Student类,因此该类是一个序列化类,可以用于创建序列化对象,但是在该类中没有指定serialVersionUID属性,所以该类并不能保证序列化对象的版本一致。

2)向文件中保存序列化对象的类WriteStudent

说 明

上面的代码创建了一个向文件中保存序列化对象的WriteStudent类,该类用于将Student类创建的序列化对象stud及其属性id和name保存到文件(D:\object.txt)中。

3)从文件中读取序列化对象的类ReadStudent

说 明

上面的代码创建了一个ReadStudent类,该类用于从文件(D:\object.txt)中读取序列化对象,即读取使用WriteStudent类保存的序列化对象stud,进而读取该对象的id属性和name属性。

程序的运行步骤如下:

①首次执行程序时,应先执行WriteStudent类,其作用是将Student类创建的stud对象以及其属性id和name保存到文件(D:\object.txt)中,其中属性id的值是 “18” ,name的值是 “小强” ,并且执行WriteStudent类还将在控制台显示如图3.7 所示的信息,说明成功地将序列化对象保存到文件中了。

图3.7 序列化对象保存成功的提示信息

②执行ReadStudent类来测试是否可以从文件(D:\object.txt)中读取序列化对象stud以及其属性id和name,也就是进行反序列化,执行该类将在控制台显示如图3.8 所示的信息,从图中可以看到该类成功地从序列化对象stud中读取到其属性id和name的值,分别是 “18” “小强”。

图3.8 反序列化成功

说 明

由于是第1次执行程序,所以一定要先执行第1步保存序列化对象,然后再执行第 2步从文件中读取序列化对象及其属性,程序执行完上述两步是不会产生任何错误的,这是由于当执行第1步之后,并没有对Student类的属性进行任何更改(即没有在Student类中再添加任何属性,如没有在Student类的代码中添加private int age;这样的语句,也没有删除原有的id和name属性等),所以在执行第2步时,是可以从文件中读取到序列化对象及其属性的。

③ 在Student类中添加属性age,也就是在下面第一段原代码下面添加属性age并保存,添加后的代码如下第二段代码所示。

④ 直接执行ReadStudent类从序列化对象中读取数据,这时,程序会在控制台输出如图3.9 所示的异常信息。

图3.9 反序列化对象时显示的异常提示信息

说 明

程序执行完第3步和第4步后,之所以会发生异常,是由于在第3步对Student类的属性进行了更改,即在Student类中添加age属性,所以在反序列化对象时发生了如图3.9 所示的序列化对象版本不一致的异常。

技 巧

为了避免由于对创建序列化对象的类(如本实例中的Student类)的属性修改后,导致反序列化失败,可以在创建序列化类时添加serialVersionUID属性,并为该属性指定一个长整型数值,来保证序列化对象的版本一致,也就是说,如果在第1步执行程序前将Student类中serialVersionUID属性所在行的注释取消,即将Student类中 标记处的注释取消,这样程序就不会出现上述异常了。 k6rT08JV65uB4AO/k0KwqiX9FOMILzR1vnkxM3gwbW03JVTAZubSyuz5EVP0IvwR

点击中间区域
呼出菜单
上一章
目录
下一章
×