2.8.1 序列化所有组件

serialize 方法在每个需要序列化的对象上 递归调用,该方法会创建需要的 XML 文件、填充 引用表,并且用对象的内容来填充 XML 文件,下面是一些细节讨论:

对象引用表

String id = Integer.toString(table.size());
table.put(source, id);
  • 为序列化对象创建一个 唯一标识符,这里使用引用表的大小 table.size() 作为对象的唯一标识符(why?)。
  • 使用序列化对象作为 key,对象的唯一标识符作为 value,存入引用表 table 中。
  • 若已存入 table 的对象 再次遇到,可根据 对象 key 轻易查询到其 唯一标识符,因为对象的 序列化版本 已经存入 XML 文件中,所以对象 key(实际为对象引用)可被替换为对象的 唯一标识符,从而 每个对象 只有 一个 XML 副本 存在。

对象 -> XML 元素

Class sourceClass = source.getClass();
Element objElement = new Element("object");
// 对象 `Class` 名字
objElement.setAttribute("class", sourceClass.getName());
// 对象唯一标识符
objElement.setAttribute("id", id);
target.getRootElement().addContent(objElement);
  • 每个对象 对应一个 XML 元素
  • 将对象的 Class 名字和唯一标识符作为元素属性存储。
  • serialize(source, new Document(new Element("serialized")), new IdentityHashMap<Object, String> table),在 serialize 方法最初的调用参数中,source 作为 初始序列化对象,通过在每个组件对象上 递归 调用 serialize 方法,每个对象最后都有一个 对应的 XML 文件

字段 -> XML 元素

// 获取对象所有 实例字段(non-static)
Field[] fields = Util.getInstanceVariables(source);
for (Field f : fields) {
  // 设置 non-public 字段的访问权限
  if (! Modifier.isPublic(f.getModifiers())) {
    f.setAccessible(true);
  }
  // 字段 -> XML 元素
  Element fieldElement = new Element("field");
  // 字段名
  fieldElement.setAttribute("name", field.getName());
  // 声明类
  fieldElement.setAttribute("declaringClass", field.getDeclaringClass().getName());
  Class fieldType = f.getType();  // 字段类型
  Object fieldValue = f.get(source);  // 字段值
  // transient 字段无需序列化
  if (Modifier.isTransient(field.getModifiers())) {
    fieldValue = null;
  }
  fieldElement.addContent(serializeVariable(fieldType, fieldValue, target, table));
  objElement.addContent(fieldElement);
}
  • 每个字段 对应一个 XML 元素
  • transient 修饰符表示该字段 不需要 序列化。

数组

Class componentClass = sourceClass.getComponentClass();
int length = Array.getLength(componentClass);
objElement.setAttribute("length", Integer.toString(length));
for (int i = 0; i < length; i++) {
  // 添加每个数组元素对应的 XML 元素
  objElement.addContent(serializeVariable(componentClass,
                        Array.get(source, i),
                        target,
                        table));
}
  • 数组只需要遍历数组元素,将所有元素对应的 XML 元素添加到数组对象的 XML 元素即可。
  • Array 统一了 原始类型数组对象数组 的处理方式,从而在程序中无需关系数组元素的具体类型。

results matching ""

    No results matching ""