序列化过程:序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,
当反序列化时系统会去检测文件中的serialVersionUID,
判断它是否与当前类的serialVersionUID一致,
如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。
serialVersionUID有两种显示的生成方式:
一是默认的1L,比如:private static final long serialVersionUID = 1L;
二是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:
private static final long serialVersionUID = xxxxL;
1 当实现java.io.Serializable接口的类没有显式地定义一个serialVersionUID变量时候,
Java序列化机制会根据编译的Class自动生成一个serialVersionUID作序列化版本比较用,
这种情况下,如果Class文件(类名,方法明等)没有发生变化(增加空格,换行,增加注释等等),
就算再编译多次,serialVersionUID也不会变化的。
2 如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,
就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。
当两次序列化的版本号serialVersionUID不一致时,会导致:
[Java] 纯文本查看 复制代码 Exception in thread "main" java.io.InvalidClassException: com.demo.seriDemo.DataObject; local class incompatible: stream classdesc serialVersionUID = 1175939230834636559, local class serialVersionUID = -7343438723219659897
注意:
(1)静态成员是不能被序列化的,因为静态成员是随着类的加载而加载的,与类共存亡,并且静态成员的默认初始值都是0;
能被序列化的只是某个对象的成员.
(2)如果同时在一次代码执行中进行序列化和反序列化,此时类中的静态成员是有值的,并不是因为静态的成员
能够被序列化,而是此次运行jvm保存了静态成员。所以会发现好像静态成员被序列化和反序列化一样。
代码如下:
[Java] 纯文本查看 复制代码 public static void main(String[] args) throws Exception {
// 序列化DataObject对象
Serialize();
// 反序列DataObject对象
DataObject object = Deserialize();
// 静态成员属于类级别的,所以不能序列化,序列化只是序列化了对象而已,
// 这里的不能序列化的意思,是序列化信息中不包含这个静态成员域,下面
// 之所以i输出还是2,是因为测试都在同一个机器(而且是同一个进程),因为这个jvm
// 已经把i加载进来了,所以获取的是加载好的i,如果是传到另一台机器或者关掉程序重新
// 写个程序读入DataObject.txt,此时因为别的机器或新的进程是重新加载i的,所以i信息就是初始时的信息,即0
System.out.println(object);
}
/**
* MethodName: SerializePerson
* Description: 序列化对象
* @author
* @throws FileNotFoundException
* @throws IOException
*/
private static void Serialize() throws FileNotFoundException, IOException {
DataObject object = new DataObject();
object.setName("张三");
object.setAge(10);
// 创建ObjectOutputStream对象输出流,其中用到了文件的描述符对象和文件输出流对象
ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
new File("DataObject.txt")));
// 将DataObject对象存储到DataObject.txt文件中,完成对DataObject对象的序列化操作
oo.writeObject(object);
System.out.println("对象序列化成功!");
// 最后一定记得关闭对象描述符!!!
oo.close();
}
/**
* MethodName: DeserializePerson
* Description: 反序列DataObject对象
* @author
* @return
* @throws Exception
* @throws IOException
*/
private static DataObject Deserialize() throws Exception, IOException {
// 创建ObjectInputStream对象输入流,其中用到了文件的描述符对象和文件输入流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
new File("DataObject.txt")));
// 从DataObject.txt文件中读取DataObject对象,完成对DataObject对象的反序列化操作
DataObject object = (DataObject) ois.readObject();
System.out.println("对象反序列化成功!");
// 最后一定记得关闭对象描述符!!!
ois.close();
return object;
}
|