Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化Deserialization是一种将这些字节重建成一个对象的过程。【字节流的来回转换】
Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。
将对象状态转换成字节流之后,可以用java.io包中各种字节流的类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机。对象序列化功能非常简单、强大,在RMI、Socket、JMS、EJB都有应用。对象序列化问题在网络编程中并不是最核心的课题,但却相当重要,具有许多实用意义。
java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的“深复制”,即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象的序列。
一个对象能够序列化的前提是实现Serializable接口,Serializable接口没有方法,更像是个标记。有了这个标记的Class就能被序列化机制处理。使用ObjectInputStream 和ObjectOutputStream 进行对象的读写。
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
public int id;
public String name;
public ObjectSer(int id, String name) {
this.id = id;
this.name = name;
}
public static void main(String args[]) throws Exception {
String file = "student.ser";
// Serializable
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
outputStream.writeObject(new Student(123, "Jacky"));
outputStream.close();
// Deserializable
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file));
System.out.println(inputStream.readObject());
inputStream.close();
}
}
输出的文件“student.ser”是二进制格式的,相当于把Student对象转化成一个二进制的串。而且我们发现其实Student中只有很少的属性,但是文件中信息量倒是不小,这是因为其中除了数据内容以外,还包含了对象结构的描述。
我通过EditPlus十六进制查看“student.ser”。8位表示一个byte,所以两位十六进制数表示一个byte,如下:
AC ED 00 05 73 72 00 24 63 6F 6D 2E 6A 73 63 61
69 2E 6A 61 76 61 2E 73 65 72 69 61 6C 69 7A 61
74 69 6F 6E 2E 53 74 75 64 65 6E 74 00 00 00 00
00 00 00 01 02 0002 49 00 02 6964 4C 00 04 6E
61 6D 65 74 00 12 4C 6A 61 76 61 2F 6C 616E 67
2F 53 74 72 69 6E 67 3B 78 7000 00 00 7B74 00
05 4A 61 63 6B 79
开头部分,见颜色:
AC ED : STREAM_MAGIC. 声明使用了序列化协议。
00 05 : STREAM_VERSION. 序列化协议版本。
73 : TC_OBJECT. 声明这是一个新的对象。
接下来输出 Student 类的描述,这是序列化类的第一步,见颜色:
72 : TC_CLASSDESC. 声明这里开始一个新 Class 。
00 24 : Class 名字的长度,所以接下去的0x24(即36)个byte就是表示类全名:com.jscai.java.serialization.Student
接着是序列化信息,见颜色:
00 00 0000 00 00 00 01 : serialVersionUID=1L
02 : 支持序列化。
field的信息,见颜色和颜色:
00 02 : 类中有2个属性。
49 : 类型int; 00 02 : 属性名长度2; 69 64 :属性名id.
4C : 类型String; 00 04 :属性名长度4; 6E 61 6D 65 :name.
74 : TC_STRING. 代表一个 new String. 用 String 来引用对象。
00 12 : 长度为0x12(即18),表示类型 Ljava/lang/String
类信息描述结束,见7870:
78 : TC_ENDBLOCKDATA, 对象块结束的标志。
70 : TC_NULL, 说明没有其他超类的标志。
最后是field的属性值,见颜色:
00 00 007B : int占4个byte,对应第一个属性,表示id=123。
74 : TC_STRING;00 05 : 长度为5; 4A61 63 6B 79 : 内容为Jacky
【具体可见java.io.ObjectStreamConstants,包含所有的类型码。String的表示方法算是一个很典型的例子,先是类型标识,紧跟长度和内容,让JDK知道转换策略以及读取的长度。 JDK对象的序列化策略,具体可以参考我的《初探Java序列化(2)-writeObject/readObject》】
参考http://longdick.iteye.com的博文