0

我正在使用 JAXB 将对象保存到 xml 文件中。

@XmlRootElement(name="jaxbobjt")
@XmlAccessorType(XmlAccessType.FIELD)
public class SomeJAXBObject
{

  @XmlElementWrapper(name="myEntry")
  private Map<Integer, AnotherJAXBObject> map = Collections.synchronizedMap(new LinkedHashMap<Integer, AnotherJAXBObject>());
}

请注意我正在使用synchronizedMap(...)包装器这一事实。

上面的结果如下 xml:

<jaxbobjt>
  <map>
    <myEntry>
      <key>key</key>
      <value>value</value>
    </myEntry>
  </map>
</jaxbobjt>

实际上,我认为我需要一个XmlAdapter才能使这个工作。但令我惊讶的是,这可以很好地编组和解组。测试表明它正确地使用了一个java.util.Collections$SynchronizedMap包含LinkedHashMap$Entry对象。

所以,如果我理解正确的话。JAXB 的解组器,只是使用构造函数实例化我的对象。由于在实例化对象后已经有一个映射实例,因此它不会实例化映射本身。它使用putAll我假设?

我只是想更深入地了解正在发生的事情。如果有人能给我更多关于这方面的背景信息,那就太好了。我的假设正确吗?

如果我是正确的,我假设以下实现会失败:

@XmlRootElement(name="jaxbobjt")
@XmlAccessorType(XmlAccessType.FIELD)
public class SomeJAXBObject
{
  // no instance yet.
  @XmlElementWrapper(name="myEntry")
  private Map<Integer, AnotherJAXBObject> map = null;

  public synchronized void addObject(Integer i, AnotherJAXBObject obj)
  {
    // instantiates map on-the-fly.
    if (map == null) map = Collections.synchronizedMap(new LinkedHashMap<Integer, AnotherJAXBObject>());
    map.put(i, obj);
  }
}
4

1 回答 1

0

JAXB 使用的策略是仅在必要时创建容器类。对于绑定到列表的任何内容,JAXB 的 xjc 创建

protected List<Foo> foos;
public List<Foo> getFoos(){
    if( foos == null ) foos = new ArrayList<>();
    return foos;
}

因此,解组另一个 Foo 以添加到此列表中,本质上确实

parent.getFoos().add( foo );

至于地图:大概您的类的工作版本SomeJAXBObject包含一个getMap方法,并且以相同的方式工作。列表和地图的设置器不是必需的,如果存在它们也不会被使用。也不需要父类中的 put 方法;如果存在,则不会使用它,因为 JAXB 无法知道它的作用。

于 2015-11-16T14:27:54.263 回答