2015-11-16 3 views
0

Я использую JAXB для сохранения объектов в xml-файлах.unmarshal synchronized map

@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's 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); 
    } 
} 

ответ

0

Стратегия используется JAXB заключается в создании классов контейнеров только тогда, когда это необходимо. Для чего-либо, привязанной к списку, XJC JAXB создает

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 не будет знать, что он делает.

+0

'@ XmlAccessorType' настроен на тип' FIELD'. Но я думаю, в сущности, это одно и то же: 'parent.foos.add (foo)', правильно? – bvdb

+0

Тип Accessor в основном предназначен для определения выбора элементов, которые должны быть (un) упорядочены. Он не говорит, какой метод доступа фактически используется, и публичный геттер будет первым выбором. – laune