Java序列化(Serialization)的理解

一、什么是序列化

  Java是面向对象的编程语言,有时须要保存对象,并在下次使用时能够顺利还原该对象。因为这种需求很常见,因此Java API对此提供了支持,添加相关程序代码到标准类库中,并将保存和还原的过程称之为“对象序列化”。
  Java SE7 文档中将与对象序列化的相关内容作了详细表述,将其称为:
  “Java对象序列化规范”  Java Object Serialization Specification,网址为:
  http://docs.oracle.com/javase/7/docs/platform/serialization/spec/serialTOC.html


二、为何叫序列化

  我的猜想:
  因为保存对象的过程,是把对象保存为一连串字节流,而英文Serialization的意思“序列化”,因此序列化形象的表述了这个过程。


三、序列化保存那些内容

  对象(object)是类(class)的一个实例(instance)。一个类中包含了变量(field)和函数(method)两个部分。同一个类的不一样对象只是变量不一样,因此Java API序列化过程当中只保存了对象的变量部分。一样,因为静态变量(static field)是由同一个类的各个对象共用的,因此序列化过程当中也不保存。
  因为还原对象时须要在程序中动态建立该对象,因此程序也须要知道该对象的类定义,因此若是对象由一个程序序列化保存以后,由另一个程序反序列化还原时,类文件也须要传送给该程序。这就须要扩展Java API序列化的功能,对其进行自定义。Java的远程方法调用(Remote Method Invocation, RMI)功能,就是以Java API序列化为基础,并进行了扩展。




三、序列化的用途

 序列化主要有三个用途:
  • 对象持久化(persistence)
  对象持久化是指延长对象的存在时间。一般情况下,当程序结束时,程序中的对象再也不存在。
  若是经过序列化功能,将对象保存到文件中,就能够延长对象的存在时间,在下次程序运行是再恢复该对象。
  序列化将对象保存在文件中,是实现对象持久化的一种方式。持久化还有不少种方式,好比Hibernate框架就提供了一整套对象持久化的方案。
  • 对象复制
  经过序列化,将对象保存在内存中,能够再经过此数据获得多个对象的副本。
  • 对象传输
  经过序列化,将对象转化字节流后,能够经过网络发送给另外的Java程序。


四、什么是流(Stream)

  Java是面向对象的编程语言,对象是对现实实体的抽象表述。因此Java API中流(Stream)是对一连串数据的抽象,同时定义了一些操做,write和read等。因此现实实体,只要包含数据和对数据的读写操做均可以表示为流。OutputStream类和InputStream类,是2个抽象类,分别对应输出、输入流,全部其它流对象,都是其子类。
  好比文件,文件本质是保存在存储设备中的一连串数据,在Java API中抽象为FileOutputStream类和FileInputStream类,文件的读写能够经过对相应流的读写实现的。
  好比控制台中命令和结果的输入输出,键盘的输入是一串数据,程序的输出是一串数据,因此在Java API中也被抽象为流对象。控制台输入由System.in对象体现,System.in是类型为InputStream的对象。控制台输出由System.out对象体现,System.out是类型为PrintStream的对象。
  因为文件和控制台输入输出都和操做系统有关,因此文件流和控制台流对象最终都是由Java虚拟机建立的。
  ByteArrayOutputStream、ByteArrayInputStream,是彻底不依赖Java虚拟机的流对象,其彻底是对一个byte[]数组的抽象。由于byte[]数组也是一连串数据,byte[]数组支持读写功能,因此彻底能够抽象为流对象,这能够从这两个类的源代码中看出。


四、使用序列化功能

  在Java API中,对象序列化接口主要由两个类提供:ObjectOutputStream,ObjectInputStream。
  为了知足保存到文件、内存、经过网络传输等不一样需求,对象序列化后保存在流对象中。提供不一样的流对象时,序列化后保存在相应流对象中。好比提供FileOutputStream和FileInputStream,就保存在文件中;提供ByteArrayOutputStream、ByteArrayInputStream,就保存在内存中。
  因为Java API已经提供了实现序列化须要的相关代码,因此大部分状况下,使用序列化很简单。例如:
  保存对象:
//建立一个流对象,好比文件输出流对象
FileOutputStream underlyingStream = new FileOutputStream("C:\\temp\\test");
//用刚才的文件流,建立一个对象序列化输出流
ObjectOutputStream serializer = new ObjectOutputStream(underlyingStream);
//使用该流的输出函数,将对象序列化后保存到文件流中,也就是保存到了对应文件中。
serializer.writeObject(serializableObject);


  读取对象,操做彻底与保存是一一对应:
//建立一个流对象,好比文件输入流对象
FileInputStream underlyingStream = new FileInputStream("C:\\temp\\test");
//用刚才的文件流,建立一个对象序列化输入流
ObjectInputStream deserializer = new ObjectInputStream(underlyingStream);
//使用该流的输入函数,将文件中保存的对象读取到内存中,并建立相应对象。
Object deserializedObject = deserializer.readObject(  );



五、什么样的类能够序列化

  不是全部的类都有序列化的必要,好比Thread类等,这些类中并无必要保存的信息。这也是序列化没有成为Java内部功能的缘由之一。因此,若是某个类须要序列化功能,类的定义中必须实现Serializable或者Externalizable接口。
  好比Java API中的Character类:
public final
class Character implements java.io.Serializable, Comparable<Character>





六、进一步的内容

  进一步的内容好比transient关键字、自定义序列化机制、序列化版本控制等,请参考如下文章: html

  Java RMI  Chapter 10  Serialization  By William Grosso   http://oreilly.com/catalog/javarmi/chapter/ch10.html   Discover the secrets of the Java Serialization API   by Todd Greanier   http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html   Ivor Horton's Beginning Java(Java 7 Edition By Ivor Horton)  Chapter 12  Serializing Object   http://cn.bing.com/search?q=beginning+java+java+7+edition&go=&qs=AS&form=QBRE&pq=beginning+java+java&sc=2-19&sp=1&sk=
相关文章
相关标签/搜索