解组同步映射
unmarshal synchronized map
我正在使用 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
才能让它工作。
但令我惊讶的是,这个 marshals 和 unmarshals 都很好。测试显示它正确地使用了包含 LinkedHashMap$Entry
对象的 java.util.Collections$SynchronizedMap
。
所以,如果我没理解错的话。 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);
}
}
JAXB 使用的策略是仅在必要时创建容器 classes。对于绑定到列表的任何内容,JAXB 的 xjc 创建
protected List<Foo> foos;
public List<Foo> getFoos(){
if( foos == null ) foos = new ArrayList<>();
return foos;
}
因此,解组另一个 Foo 以添加到此列表中,本质上是
parent.getFoos().add( foo );
至于地图:大概您的 class SomeJAXBObject
的工作版本包含一个 getMap
方法,并且其工作方式相同。列表和地图的设置器不是必需的,如果存在它们也不会被使用。父 class 中的 put 方法也不是预期的;如果存在,它将不会被使用,因为 JAXB 无法知道它的作用。
我正在使用 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
才能让它工作。
但令我惊讶的是,这个 marshals 和 unmarshals 都很好。测试显示它正确地使用了包含 LinkedHashMap$Entry
对象的 java.util.Collections$SynchronizedMap
。
所以,如果我没理解错的话。 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);
}
}
JAXB 使用的策略是仅在必要时创建容器 classes。对于绑定到列表的任何内容,JAXB 的 xjc 创建
protected List<Foo> foos;
public List<Foo> getFoos(){
if( foos == null ) foos = new ArrayList<>();
return foos;
}
因此,解组另一个 Foo 以添加到此列表中,本质上是
parent.getFoos().add( foo );
至于地图:大概您的 class SomeJAXBObject
的工作版本包含一个 getMap
方法,并且其工作方式相同。列表和地图的设置器不是必需的,如果存在它们也不会被使用。父 class 中的 put 方法也不是预期的;如果存在,它将不会被使用,因为 JAXB 无法知道它的作用。