[关闭]
@contribute 2016-01-11T03:48:03.000000Z 字数 1968 阅读 1363

java.io.Serializable浅析

java


1、序列化是干什么的?

简单说就是为了保存在内存中的各种对象的状态,并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存Object States,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。

2、什么情况下需要序列化

3、当对一个对象实现序列化时,究竟发生了什么?

在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如:

  1. Foo myFoo = new Foo();
  2. myFoo .setWidth(37);
  3. myFoo.setHeight(70);

当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。

  1. FileOutputStream fs = new FileOutputStream("foo.ser");
  2. ObjectOutputStream os = new ObjectOutputStream(fs);
  3. os.writeObject(myFoo);

4、实现序列化(保存到一个文件)的步骤

  1. FileOutputStream fs = new FileOutputStream("foo.ser");
  2. ObjectOutputStream os = new ObjectOutputStream(fs);
  3. os.writeObject(myObject1);
  4. os.close();

5、相关注意事项

6、serialVersionUID

序列化运行时使用一个称为serialVersionUID的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的serialVersionUID与对应的发送者的类的版本号不同,则反序列化将会导致InvalidClassException。可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化类未显式声明serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID值,如“Java(TM)对象序列化规范”中所述。不过,

  1. 强烈建议所有可序列化类都显式声明serialVersionUID值,原因是计算默认的serialVersionUID对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的InvalidClassException。因此,为保证serialVersionUID值跨不同java编译器实现的一致性,序列化类必须声明一个明确的serialVersionUID值。
  2. 强烈建议使用private修饰符显示声明serialVersionUID(如果可能),原因是这种声明仅应用于直接声明类serialVersionUID字段作为继承成员没有用处。数组类不能声明一个明确的serialVersionUID,因此它们总是具有默认的计算值,但是数组类没有匹配serialVersionUID值的要求。
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注