1、 一个对象能够序列化的前提是实现Serializable接口或Externalizable接口,Serializable接口没有方法,更像是个标记。有了这个标记的Class就能被序列化机制处理。
2、 写个程序将对象序列化并输出。ObjectOutputStream能把Object输出成Byte流。
3、 要从持久的文件中读取Bytes重建对象,我们可以使用ObjectInputStream。
在序列化时,有几点要注意的:
l 当一个对象被序列化时,只序列化对象的非静态成员变量,不能序列化任何成员方法和静态成员变量。
l 如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
l 如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。可以通过将这个引用标记为transient,那么对象仍然可以序列化。对于一些比较敏感的不想序列化的数据,也可以采用该标识进行修饰。
5、对象的序列化格式 5.1 简单对象的序列化介绍package com.asc.alibaba.base;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
publicclassTestSerial implements Serializable{
publicbyteversion = 100;
publicbytecount = 0;
publicstaticvoid main(String[] args) throws IOException, ClassNotFoundException {
FileOutputStream fos = new FileOutputStream("temp.out");
ObjectOutputStream oos = new ObjectOutputStream(fos);
TestSerialize testSerialize = new TestSerialize();
oos.writeObject(testSerialize);
oos.flush();
oos.close();
}
}
}
将一个对象序列化后是什么样子呢?打开刚才将对象序列化输出的temp.out文件,以16进制方式显示。内容应该如下:
AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 6573 74 A0 0C 34 00 FE B1 DD F9 02 00 02 42 00 0563 6F 75 6E 74 42 00 07 76 65 72 73 69 6F 6E 7870 00 64这一堆字节就是用来描述序列化以后的TestSerial对象的,我们注意到TestSerial类中只有两个域:
public byte version = 100;
public byte count = 0;
且都是byte型,理论上存储这两个域只需要2个byte,但是实际上temp.out占据空间为51bytes,也就是说除了数据以外,还包括了对序列化对象的其他描述。
开头部分,见颜色:
² AC ED: STREAM_MAGIC. 声明使用了序列化协议.
² 00 05: STREAM_VERSION. 序列化协议版本.
² 0x73: TC_OBJECT. 声明这是一个新的对象.
输出TestSerial类的描述。见颜色:
² 0x72: TC_CLASSDESC. 声明这里开始一个新Class。
² 00 0A: Class名字的长度.
² 53 65 72 69 61 6c 54 65 73 74: TestSerial,Class类名.
² 05 52 81 5A AC 66 02 F6: SerialVersionUID, 序列化ID,如果没有指定,
则会由算法随机生成一个8byte的ID.
² 0x02: 标记号. 该值声明该对象支持序列化。
² 00 02: 该类所包含的域个数。
输出域的信息,见颜色:
² 0x42: 域类型. 42 代表"B", 也就是byte;
² 00 05: 域名字的长度;
² 636F 75 6E 74: count,域名字描述count;
² 0x42: 域类型. 42 代表"B", 也就是byte;