最近常被问到对象存储的一些问题。所以决定整理一下着方面经验。
把Java对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为Java对象的过程称为对象的反序列化。
对象的序列化主要有两种用途:
(1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
(2) 在网络上传送对象的字节序列。
以上简单介绍了序列化的定义,它主要作用就是将对象转换为可存储的字节,这样我们就能方便的存储并还原对象。
例如,游戏中复杂场景的还原,游戏的实时保存,工具软件中的“返回上一步”功能,或者,仅仅是用来存储软件状态等等。
其实,序列化是很常用的一个技术,只是J2ME中为求精简,取消了关于序列化的一些内容。所以我们只能自己来实现它。
当然,它也是相当简单的,只是很多朋友在理解上存在一些障碍。下面是示范代码:
public class SerializeMIDlet extends MIDlet implements CommandListener {
SerializeTest test1;
SerializeTest test2;
Form formTest;
Command cmdExit;
public SerializeMIDlet() {
formTest = new Form("SerializeTest");
cmdExit = new Command("Exit", Command.EXIT, 0);
formTest.addCommand(cmdExit);
formTest.setCommandListener(this);
Display.getDisplay(this).setCurrent(formTest);
test1 = new SerializeTest(1, 1000, "SerializeTest", true);
test2 = new SerializeTest();
byte[] data = test1.serialize();
test2.deserialize(data);
formTest.append("test1.member1 = " + Integer.toString(test1.member1)
+ " ");
formTest.append("test1.old member2 = " + Long.toString(test1.member2)
+ " ");
formTest.append("test1.member3 = " + test1.member3 + " ");
formTest.append("test1.member4 = " + test1.member4 + " ");
formTest.append(" ");
formTest.append("test2.member1 = " + Integer.toString(test2.member1)
+ " ");
formTest.append("test2.old member2 = " + Long.toString(test2.member2)
+ " ");
formTest.append("test2.member3 = " + test2.member3 + " ");
formTest.append("test2.member4 = " + test2.member4 + " ");
}
public void commandAction(Command c, Displayable d) {
if (d.equals(formTest)) {
if (c.equals(cmdExit)) {
notifyDestroyed();
}
}
}
protected void destroyApp(boolean arg0) {
}
protected void pauseApp() {
}
protected void startApp() {
}
public interface Serializable {
public byte[] serialize();
public void deserialize(byte[] data);
}
public class SerializeTest implements Serializable {
int member1;
long member2;
String member3;
boolean member4;
public SerializeTest() {
}
public SerializeTest(int m1, long m2, String m3, boolean m4) {
member1 = m1;
member2 = m2;
member3 = m3;
member4 = m4;
}
public byte[] serialize() {
byte[] ret = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeInt(member1);
dos.writeLong(member2);
dos.writeUTF(member3);
dos.writeBoolean(member4);
ret = baos.toByteArray();
dos.close();
baos.close();
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
public void deserialize(byte[] data) {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
try {
member1 = dis.readInt();
member2 = dis.readLong();
member3 = dis.readUTF();
member4 = dis.readBoolean();
dis.close();
bais.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
代码中包含了一个Serializable接口,只要继承它并且实现
public byte[] serialize();
public void deserialize(byte[] data);
函数,就能够使用序列化的功能了。
很明显,这个接口显得有些多此一举。真正使用的时候,大家可以灵活的使用,不要受这个示范代码的限制。
还有一点让人觉得遗憾的地方,就是J2ME不能支持反射等功能,所以J2ME中的序列化也整不出什么新花样出来。顶多是把byte数组换成流来表达,这样用在网络交互上更合适。