对象序列化

Java的对象序列化(Object Serialization)将那些实现了 Serializable接口的对象转换
成一个字节序列,并可以在以后将这个字节序列完全恢复为原来的对象。这一过程甚至可通
过网络进行。这意味着序列化机制能自动弥补不同操作系统之间的差异。也就是说,可以在
运行 Windows 系统的计算机上创建一个对象,将其序列化,通过网络将它发送给一台运行

Unix 系统的计算机,然后在那里准确地重新组装,而你却不必担心数据在不同机器上的表
示会不同,也不必关心字节的顺序或者其他任何细节。
就其本身来说,对象的序列化是非常有趣的,因为利用它可以实现“轻量级持久化
(lightweight persistence)”。“持久化”意味着一个对象的生存周期并不取决于程序是否
正在执行;它可以生存于程序的调用之间。通过将一个序列化对象写入磁盘,然后在重新调
用程序时恢复该对象,就能够实现持久化的效果。之所以称其为“轻量级”,是因为不能用某
种“persistent”(持久)关键字来简单地定义一个对象,并让系统自动维护其他细节问题(尽
管将来有可能实现)。相反,对象必须在程序中显式地序列化和重组。如果需要一个更严格
的持久化机制,可以考虑使用 Java数据对象(JDO)或者像 Hibernate之类的工具

 

对 Java Beans来说对象的序列化也是必需的,可参看第 14章。使用一个 Bean 时,一般
情况下是在设计阶段对它的状态信息进行配置。这种状态信息必须保存下来,并在程序启动
以后,进行恢复;具体工作由对象序列化完成。
只要对象实现了 Serializable接口(该接口仅是一个标记接口,不包括任何方法),对象的
序列化处理就会非常简单。当序列化的概念被加入到语言中时,许多标准库类都发生了改变,
以便能够使之序列化——其中包括所有原始数据类型的封装器、所有容器类以及许多其他的
东西。甚至 Class 对象也可以被序列化。
为了序列化一个对象,首先要创建某些 OutputStream对象,然后将其封装在一个
ObjectOutputStream对象内。这时,只需调用 writeObject()即可将对象序列化,并将
其发送给 OutputStream。要将一个序列重组为一个对象,需要将一个 InputStream封
装在 ObjectInputStream内,然后调用 readObject()。和往常一样,我们最后获得的是
指向一个向上转型为 Object 的句柄,所以必须向下转型,以便能够直接对其进行设置。

 

对象序列化特别“聪明”的一个地方是它不仅保存了对象的“全景图”,而且能追踪对象内包含
的所有引用并保存那些对象;接着又能对每个这样的对象内包含的引用进行追踪;以此类推。
这种情况有时被称为“对象网”,单个对象可与之建立连接,而且它还包含了对象的引用数组
以和成员对象。如果必须保持一套自己的对象序列化机制,那么维护那些可追踪到所有链接
的代码可能会显得非常麻烦。然而,由于 Java的对象序列化似乎找不出什么缺点,所以请
尽量不要自己动手,让它用优化的算法自动维护整个对象网。下面这个例子通过对链接的对
象生成一个“Worm”(蠕虫)对序列化机制进行了测试。每个对象都与 Worm中的下一段
链接,同时又与属于不同类(Data)的对象引用数组链接:

 

Java I/O流类库的确能满足我们的基本需求:我们可以通过控制台、文件、内存块甚至因
特网进行读写。通过继承,我们可以创建新类型的 input和 output对象。并且通过重新定
义 toString()方法,我们甚至可以为流接受的对象类型进行简单扩充。当我们向期望收
到一个字符串的方法传送一个对象时,会自动调用 toString()方法。(这是 Java有限的
自动类型转换功能。)

 

在 I/O 流类库的文档和设计中,仍留有一些没有解决的问题。例如,当我们打开一个文件
以便输出时,我们可以指定一旦试图覆盖该文件就抛出一个异常——有的编程系统允许我们
自行指定想要打开的输出文件,只要它尚不存在。在 Java中,我们似乎应该使用一个 File
对象来判断某个文件是否存在,因为如果我们以FileOutputStream或者FileWriter打开,
那么它肯定会被覆盖。
I/O 流类库使我们喜忧参半。它确实能做许多事情,而且具有可移植性。但是如果我们没有
理解修饰器模式,那么这种设计就不是很直觉,因此,在学习和传授它的过程中,需要额外
的开销。而且它并不完善;例如我应该可以不必去写像 TextFile 这样的应用,并且它没有
任何对输出格式化的种类的支持,而事实上其他所有语言的 I/O 包都提供这种支持。
然而,一旦我们理解了修饰器模式,并开始在某些情况下使用该类库以利用其能够提供的灵
活性,那么你就开始从这个设计中受益了。到那个时候,为此额外多写几行代码的开销应该
不至于使人觉得太麻烦。
如果你在本章没有发现想要找寻的东西(这里仅仅是一个初步介绍,其涵盖面并不全面),
可以在《Java I/O》中找到更深入的论述, Elliotte Rusty Harold 著(O’Reilly, 1999)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章