JAXB可以生成ArrayList而不是List吗?

Raj*_*Raj 4 java collections arraylist jaxb

<complexType name="BookShelf">
   <sequence>
      <choice minOccurs="0" maxOccurs="unbounded">
         <element name="newBook" type="string"/>
         <element name="oldBook" type="string"/>
      </choice>
   </sequence>
</complexType>
Run Code Online (Sandbox Code Playgroud)

JAXB生成属性作为List<JAXBElement<String>>.有没有什么方法可以生成ArrayList?

Sea*_*oyd 14

为什么,那对你有什么好处?

  1. ArrayList<E>没有公共方法没有在 List<E>界面中,所以没有什么可以用 ArrayList<E>你不能做的任何事情List<E>(实际上有一个: ArrayList.trimToSize(),谢谢@Joachim Sauer,但它几乎不需要).
  2. API接受或返回实现类型而不是底层接口是非常糟糕的做法.我建议你按照Sun Java Tutorial 的Collections Trail和/或阅读 Joshua Bloch的Effective Java (你会从这个简短的预览中了解他正在谈论的内容,这是下面引用的来源)了解有关Collections框架和界面用法的更多信息.
  3. 谁说底层列表实现不是ArrayListArrayList无论如何,这是最常用的List实现,因此JAXB实际返回的可能性很高 ArrayList,它不会告诉你(因为你不需要知道).

第52项:通过接口引用对象(摘录)

第40项包含您应该使用接口而不是类作为参数类型的建议.更一般地说,您应该倾向于使用接口而不是类来引用对象.如果存在适当的接口类型,则应使用接口类型声明参数,返回值,变量和字段.您真正需要引用对象类的唯一时间是使用构造函数创建它.为了使这个具体,请考虑这种情况 Vector,即List接口的实现.养成打字的习惯:

// Good - uses interface as type
List<Subscriber> subscribers = new Vector<Subscriber>();
Run Code Online (Sandbox Code Playgroud)

而不是这个:

// Bad - uses class as type!
Vector<Subscriber> subscribers = new Vector<Subscriber>();
Run Code Online (Sandbox Code Playgroud)

[...]

来源:有效的Java,SafariBooksOnline上的预览.

  • 项目#1并不完全正确(参见上面Arne提到的`trimToSize()`). (4认同)
  • 用另一个问题回答一个问题是很粗鲁的. (3认同)

bdo*_*han 5

默认情况下,该属性将是List,底层实现将是ArrayList.当然,您可以使用JAXB自定义来更改底层实现,或者使用自己的类具有ArrayList类型的属性(尽管出于其他答案中提到的原因,这很少是一个好主意).

默认的JAXB生成

给出您的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>
Run Code Online (Sandbox Code Playgroud)

使用以下命令行:

xjc -d out your-schema.xsd
Run Code Online (Sandbox Code Playgroud)

JAXB将生成以下类:

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

定制一代

默认情况下,JAXB的属性类型为List,底层实现为ArrayList.如果您希望控制底层实现,可以使用外部绑定文件,如:

<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>
Run Code Online (Sandbox Code Playgroud)

以下是XJC电话:

xjc -d out -b binding.xml your-schema.xsd
Run Code Online (Sandbox Code Playgroud)

改为获得以下课程:

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

使用你自己的班级:

您也可以使用自己的类与ArrayList类型的属性(虽然由于其他答案中提到的原因,这很少是一个好主意).

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

欲获得更多信息: