标签:
java 对象序列化
package org.rui.io.serializable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Random; /** * 对象 序列化 * 以下这些操作都使得事情变得更加复杂。加大了难度,然而。真正的序列化过程却是很easy的 * @author lenovo * */ class Data implements Serializable { private int n; public Data(int n){this.n=n;} public String toString(){return Integer.toString(n);} } public class Worm implements Serializable { private static Random rand=new Random(47); private Data[]d={ new Data(rand.nextInt(10)), new Data(rand.nextInt(10)), new Data(rand.nextInt(10)) }; private Worm next; private char c; // value of i==number of segments public Worm(int i,char x) { System.out.println("worm constructor;"+i); c=x; if(--i>0) next=new Worm(i,(char)(x+1)); } // public Worm(){ System.out.println("defalult constructor"); } public String toString() { StringBuilder result=new StringBuilder(); result.append(c); result.append("("); for(Data data:d) result.append(data); result.append(")"); if(next!=null) result.append(next); return result.toString(); } /////////////////////////////////////////// public static void main(String[] args) throws Exception { Worm w=new Worm(6,'a'); System.out.println(" w:"+w); //序列化到 ObjectOutputStream out=new ObjectOutputStream( new FileOutputStream("worm.out") ); out.writeObject("Worm storage\n"); out.writeObject(w); out.close(); //读取 ObjectInputStream in=new ObjectInputStream( new FileInputStream("worm.out") ); String s=(String)in.readObject(); Worm worm=(Worm)in.readObject(); System.out.println("s:"+s+" w2:"+worm); ////////////////////////////////////////////////////////// //再次写入 ByteArrayOutputStream bos=new ByteArrayOutputStream(); ObjectOutputStream oos=new ObjectOutputStream(bos); oos.writeObject("Worm storage\n"); oos.writeObject(w); oos.flush(); //读取 ObjectInputStream in2=new ObjectInputStream( new ByteArrayInputStream(bos.toByteArray()) ); s=(String)in2.readObject(); Worm w3=(Worm)in2.readObject(); System.out.println("s:"+s+" w3:"+w3); } } /**output: worm constructor;6 worm constructor;5 worm constructor;4 worm constructor;3 worm constructor;2 worm constructor;1 w:a(853)b(119)c(802)d(788)e(199)f(881) s:Worm storage w2:a(853)b(119)c(802)d(788)e(199)f(881) s:Worm storage w3:a(853)b(119)c(802)d(788)e(199)f(881) */ /** doc Java 1.1 增添了一种有趣的特性,名为“对象序列化”(Object Serialization)。它面向那些实现了 Serializable 接口的对象,可将它们转换成一系列字节,并可在以后全然恢复回原来的样子。这一过程亦可 通过网络进行。这意味着序列化机制能自己主动补偿操作系统间的差异。换句话说。能够先在Windows 机器上创 建一个对象,对其序列化,然后通过网络发给一台Unix 机器,然后在那里准确无误地又一次“装配”。不必关 心数据在不同机器上怎样表示,也不必关心字节的顺序或者其它不论什么细节。 就其本身来说,对象的序列化是很有趣的。由于利用它能够实现“有限持久化”。请记住“持久化”意味 着对象的“生存时间”并不取决于程序是否正在运行——它存在或“生存”于程序的每一次调用之间。通过 序列化一个对象,将其写入磁盘,以后在程序又一次调用时又一次恢复那个对象,就能圆满实现一种“持久”效 果。之所以称其为“有限”,是由于不能用某种“persistent”(持久)keyword简单地地定义一个对象。并 让系统自己主动照看其它全部细节问题(虽然将来可能成为现实)。相反,必须在自己的程序中明白地序列化和 组装对象。
语言里添加了对象序列化的概念后,可提供对两种主要特性的支持。Java 1.1 的“远程方法调用”(RMI) 使本来存在于其它机器的对象能够表现出好象就在本地机器上的行为。将消息发给远程对象时,须要通过对 象序列化来传输參数和返回值。RMI 将在第15 章作详细讨论。 对象的序列化也是Java Beans 必需的,后者由Java 1.1 引入。使用一个Bean 时,它的状态信息通常在设计 期间配置好。程序启动以后,这样的状态信息必须保存下来,以便程序启动以后恢复;详细工作由对象序列化 完毕。 对象的序列化处理很easy,仅仅需对象实现了Serializable 接口就可以(该接口仅是一个标记,没有方法)。 在Java 1.1 中。很多标准库类都发生了改变,以便能够序列化——当中包括用于基本数据类型的全部封装 器、全部集合类以及其它很多东西。
甚至Class 对象也能够序列化(第11 章讲述了详细实现过程)。
为序列化一个对象,首先要创建某些OutputStream 对象。然后将其封装到ObjectOutputStream 对象内。此 时,仅仅需调用writeObject()就可以完毕对象的序列化,并将其发送给OutputStream。相反的过程是将一个 InputStream 封装到ObjectInputStream 内,然后调用readObject()。和往常一样,我们最后获得的是指向 一个上溯造型Object 的句柄。所以必须下溯造型。以便能够直接设置。 对象序列化特别“聪明”的一个地方是它不仅保存了对象的“全景图”,并且能追踪对象内包括的全部句柄 并保存那些对象。接着又能对每一个对象内包括的句柄进行追踪。以此类推。我们有时将这样的情况称为“对象 网”。单个对象可与之建立连接。并且它还包括了对象的句柄数组以及成员对象。若必须自行操纵一套对象 序列化机制,那么在代码里追踪全部这些链接时可能会显得很麻烦。在还有一方面,由于Java 对象的序列化 似乎找不出什么缺点,所以请尽量不要自己动手,让它用优化的算法自己主动维护整个对象网。
以下这个样例对 序列化机制进行了測试。它建立了很多链接对象的一个“Worm”(蠕虫),每一个对象都与Worm 中的下一段链 接,同一时候又与属于不同类(Data)的对象句柄数组链接: 更有趣的是,Worm 内的Data 对象数组是用随机数字初始化的(这样便不用怀疑编译器保留了某种原始信 息)。每一个Worm 段都用一个Char 标记。
这个Char 是在反复生成链接的Worm 列表时自己主动产生的。创建一个 Worm 时。需告诉构建器希望它有多长。
为产生下一个句柄(next),它总是用减去1 的长度来调用Worm 构 318 建器。最后一个next 句柄则保持为null(空),表示已抵达Worm 的尾部。 上面的全部操作都是为了加深事情的复杂程度。加大对象序列化的难度。然而,真正的序列化过程却是很 简单的。一旦从另外某个流里创建了ObjectOutputStream,writeObject()就会序列化对象。注意也能够为 一个String 调用writeObject()。亦可使用与DataOutputStream 同样的方法写入全部基本数据类型(它们 有同样的接口)。
有两个单独的try 块看起来是相似的。第一个读写的是文件,而还有一个读写的是一个ByteArray(字节数 组)。可利用对不论什么DataInputStream 或者DataOutputStream 的序列化来读写特定的对象;正如在关于连网 的那一章会讲到的那样,这些对象甚至包括网络 能够看出。装配回原状的对象确实包括了原来那个对象里包括的全部链接。 注意在对一个Serializable(可序列化)对象进行又一次装配的过程中,不会调用不论什么构建器(甚至默认构建 器)。
整个对象都是通过从InputStream 中取得数据恢复的。 作为Java 1.1 特性的一种,我们注意到对象的序列化并不属于新的Reader 和Writer 层次结构的一部分。而 是沿用老式的InputStream 和OutputStream 结构。所以在一些特殊的场合下,不得不混合使用两种类型的层 次结构。 */
标签:
原文地址:http://www.cnblogs.com/lcchuguo/p/5350557.html