官方地址:Using Serialization with a Custom Data Format
将序列化与自定义数据格式结合使用
1. 介绍
演示如何使用?writeObject ?和? readObject 方法对自定义数据格式进行编码。当存在大量持久性数据时,该数据应以方便的精简格式存储,如本示例中使用的格式。
此示例使用一个三角形数组,一个对称的二维数组。在序列化期间,仅保存数组的一半。此示例以?writeObject 序列化数组的一半,然后通过反序列化数组的一半并复制以还原数组的另一半来还原readObject 中的整个数组。
此示例与使用序列化和可序列化字段 API 示例的不同之处在于,此示例不支持版本控制。此外,由于此示例不使用可外部化接口,因此超类不是考虑因素。
2. 源代码
码云地址:src/test/jack/io/demo/ser/case2 · Jack魏/JDK1.1源码阅读学习 - 码云 - 开源中国 (gitee.com)
import java.io.*;
public class CustomDataExample implements Serializable {
transient int dimension;
transient int thearray[][];
CustomDataExample (int dim) {
dimension = dim;
thearray = new int[dim][dim];
arrayInit();
}
public static void main(String args[]) {
CustomDataExample corg = new CustomDataExample(4);
CustomDataExample cnew = null;
try {
FileOutputStream fo = new FileOutputStream("cde.tmp");
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(corg);
so.flush();
so.close();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
try {
FileInputStream fi = new FileInputStream("cde.tmp");
ObjectInputStream si = new ObjectInputStream(fi);
cnew = (CustomDataExample) si.readObject();
si.close();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
System.out.println();
System.out.println("Printing the original array...");
System.out.println(corg);
System.out.println();
System.out.println("Printing the new array...");
System.out.println(cnew);
System.out.println();
System.out.println("The original and new arrays should be the same!");
System.out.println();
}
private void writeObject(ObjectOutputStream s)
throws IOException {
s.defaultWriteObject();
s.writeInt(dimension);
for (int i = 0; i < dimension; i++) {
for (int j = 0; j <= i; j++) {
s.writeInt(thearray[i][j]);
}
}
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
dimension = s.readInt();
thearray = new int[dimension][dimension];
for (int i = 0; i < dimension; i++) {
for (int j = 0; j <= i; j++) {
thearray[i][j] = s.readInt();
}
}
for (int i = 0; i < dimension; i++) {
for (int j = dimension - 1; j > i; j--) {
thearray[i][j] = thearray[j][i];
}
}
}
void arrayInit() {
int x = 0;
for (int i = 0; i < dimension; i++) {
for (int j = 0; j <= i; j++) {
thearray[i][j] = x;
thearray[j][i] = x;
x++;
}
}
}
public String toString() {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < dimension; i++) {
for (int j = 0; j < dimension; j++) {
sb.append(Integer.toString(thearray[i][j])+ " ");
}
sb.append("\n");
}
return(sb.toString());
}
}
3. 运行
指令运行:
javac CustomDataExample.java
java CustomDataExample
打印两个数组:
第一个数组显示序列化之前的数组。 第二个数组显示反序列化后的数组。
4. 总结
有个奇怪的地方有没有发现,我们在这个类里面写了writeObject 和readObject 方法,但是没有调用的地方,那为什么会自己调用呢? 于是我一步一步的调试,终于看到了。 如下图,在ObjectOutputStream 类里面有反射调用的(注意这里是JDK1.8版本源码)。 也可以看到调用栈,就很清楚了。
方法名必须和那个名字一样,不然都会序列化失败的,有兴趣的同学可以自己试一下哟~
|