<complexType name="BookShelf">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element name="newBook" type="string"/>
<element name="oldBook" type="string"/>
</choice>
</sequence>
</complexType>
JAXB generates the property as a List<JAXBElement<String>>
. Is there any way it can be generated as ArrayList?
ArrayList<E>
has no public
methods that are not in the
List<E>
interface, so there is
nothing you could do with the
ArrayList<E>
that you couldn't do
with any other List<E>
(actually
there is one:
ArrayList.trimToSize()
,
thanks @Joachim Sauer, but it's
hardly ever needed).ArrayList
?
ArrayList
is the most
commonly-used List implementation
anyway, so chances are high that
JAXB will actually return an
ArrayList
, it just won't tell you
so (because you don't need to know).Item 40 contains the advice that you should use interfaces rather than classes as parameter types. More generally, you should favor the use of interfaces rather than classes to refer to objects. If appropriate interface types exist, then parameters, return values, variables, and fields should all be declared using interface types. The only time you really need to refer to an object’s class is when you’re creating it with a constructor. To make this concrete, consider the case of
Vector
, which is an implementation of theList
interface. Get in the habit of typing this:
// Good - uses interface as type
List<Subscriber> subscribers = new Vector<Subscriber>();
rather than this:
// Bad - uses class as type!
Vector<Subscriber> subscribers = new Vector<Subscriber>();
[ ... ]
Source: Effective Java, preview on SafariBooksOnline.
By default the property will be a List and the underlying implementation will be an ArrayList. Of course you can use JAXB customizations to change the underlying implementation, or use your own class with a property of type ArrayList (although for the reasons mentioned in other answers this is rarely a good idea).
Default JAXB Generation
Given your XML Schema:
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<complexType name="BookShelf">
<sequence>
<choice minOccurs="0" maxOccurs="unbounded">
<element name="newBook" type="string"/>
<element name="oldBook" type="string"/>
</choice>
</sequence>
</complexType>
</schema>
Using the following command line:
xjc -d out your-schema.xsd
JAXB will generate the following class:
package generated;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BookShelf", propOrder = {
"newBookOrOldBook"
})
public class BookShelf {
@XmlElementRefs({
@XmlElementRef(name = "newBook", type = JAXBElement.class),
@XmlElementRef(name = "oldBook", type = JAXBElement.class)
})
protected List<JAXBElement<String>> newBookOrOldBook;
public List<JAXBElement<String>> getNewBookOrOldBook() {
if (newBookOrOldBook == null) {
newBookOrOldBook = new ArrayList<JAXBElement<String>>();
}
return this.newBookOrOldBook;
}
}
Customizing the Generation
By default JAXB will have the property type be List with the underlying implementation being ArrayList. If you wish to control the underlying implementation you can use an external binding file like:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="f3.xsd">
<jxb:bindings node="//xs:complexType[@name='BookShelf']/xs:sequence/xs:choice">
<jxb:property collectionType="java.util.LinkedList"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
And the following XJC call:
xjc -d out -b binding.xml your-schema.xsd
To get the following class instead:
package generated;
import java.util.LinkedList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BookShelf", propOrder = {
"newBookOrOldBook"
})
public class BookShelf {
@XmlElementRefs({
@XmlElementRef(name = "oldBook", type = JAXBElement.class),
@XmlElementRef(name = "newBook", type = JAXBElement.class)
})
protected List<JAXBElement<String>> newBookOrOldBook = new LinkedList<JAXBElement<String>>();
public List<JAXBElement<String>> getNewBookOrOldBook() {
if (newBookOrOldBook == null) {
newBookOrOldBook = new LinkedList<JAXBElement<String>>();
}
return this.newBookOrOldBook;
}
}
Using your own class:
You can also use your own class with a property of type ArrayList (although for the reasons mentioned in other answers this is rarely a good idea).
package com.example;
import java.util.ArrayList;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BookShelf", propOrder = {
"newBookOrOldBook"
})
public class BookShelf {
@XmlElementRefs({
@XmlElementRef(name = "oldBook", type = JAXBElement.class),
@XmlElementRef(name = "newBook", type = JAXBElement.class)
})
protected ArrayList<JAXBElement<String>> newBookOrOldBook ;
public ArrayList<JAXBElement<String>> getNewBookOrOldBook() {
if (newBookOrOldBook == null) {
newBookOrOldBook = new ArrayList<JAXBElement<String>>();
}
return this.newBookOrOldBook;
}
}
For More Information:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With