unmarshal synchronized map

时间:2015-11-16 10:43:30

标签: java jaxb xmladapter

我正在使用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的unmarshaller,只是使用构造函数实例化我的对象。由于在实例化对象之后已经存在地图实例,因此它不会实例化地图本身。它使用我假设的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);
  }
}

1 个答案:

答案 0 :(得分:0)

JAXB使用的策略是仅在必要时创建容器类。对于绑定到List的任何内容,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无法知道它的作用。