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

发布于 2024-10-13 12:31:35 字数 419 浏览 2 评论 0 原文

<complexType name="BookShelf">
   <sequence>
      <choice minOccurs="0" maxOccurs="unbounded">
         <element name="newBook" type="string"/>
         <element name="oldBook" type="string"/>
      </choice>
   </sequence>
</complexType>

JAXB 将属性生成为 List>。有什么办法可以将其生成为ArrayList吗?

<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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

断肠人 2024-10-20 12:31:35

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

  1. ArrayList 没有公共
    方法中没有的方法
    列表 接口,所以有
    你无能为力
    ArrayList 你做不到
    与任何其他 List (实际上
    有一个:
    ArrayList.trimToSize( )
    谢谢@Joachim Sauer,但它是
    几乎不需要)。
  2. 对于 API 来说这是一种糟糕的做法
    接受或返回实施
    类型而不是底层
    接口。我建议你
    遵循 Collections Trail
    Sun Java 教程和/或阅读
    Joshua Bloch 的《Effective Java》
    (你就会知道他是什么
    谈论这个简短的
    预览
    ,这是下面引用的来源)以了解有关
    集合框架和接口
    用法。
  3. 谁说底层列表
    实现不是 ArrayList 吗?
    ArrayList 是最多的
    常用的List实现
    无论如何,所以可能性很高
    JAXB 实际上会返回一个
    ArrayList,它只是不会告诉你
    所以(因为你不需要知道)。

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

第 40 项包含您的建议
应该使用接口而不是
类作为参数类型。更多的
一般来说,你应该赞成使用
接口而不是类
指对象。 如果合适的话
接口类型存在,那么
参数、返回值、变量、
和字段都应该被声明
使用接口类型。
唯一一次
你真的需要参考
对象的类是您创建时的
它与构造函数。为了使这个
具体来说,考虑以下情况
Vector,这是一个实现
List 界面的。进入
输入此内容的习惯:

// Good - uses interface as type
List<Subscriber> subscribers = new Vector<Subscriber>();

而不是这个:

// Bad - uses class as type!
Vector<Subscriber> subscribers = new Vector<Subscriber>();

[...]

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

Why, what good would that do you?

  1. 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).
  2. It's awful practice for an API to
    accept or return implementation
    types instead of the underlying
    interfaces. I'd suggest you to
    follow the Collections Trail of
    the Sun Java Tutorial and / or read
    Effective Java by Joshua Bloch
    (you'll get an idea of what he's
    talking about from this short
    preview
    , which is the source of the quote below) to learn more about the
    Collections framework and interface
    usage.
  3. Who says the underlying List
    implementation isn't 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 52: Refer to Objects by their Interfaces (excerpt)

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 the List 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.

岁月蹉跎了容颜 2024-10-20 12:31:35

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

默认 JAXB 生成

给定您的 XML 模式:

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

使用以下命令行:

xjc -d out your-schema.xsd

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

}

自定义生成

默认情况下,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>

和以下 XJC 调用:

xjc -d out -b binding.xml your-schema.xsd

要改为获取以下类:

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

}

使用您自己的类:

您还可以使用您自己的类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;
    }

}

了解更多信息:

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:

夜吻♂芭芘 2024-10-20 12:31:35

您无法更改 API 生成列表的事实。

但是,假设底层实现实际上生成了一个 ArrayList,您始终可以将其转换为 ArrayList:

ArrayList<JAXBElement<String>> arrayList = 
        (ArrayList<JAXBElement<String>>) list;

或者如果它不是一个 arraylist(即尝试上述操作时出现异常...),您可以生成一个新的 ArrayList,其中包含列表中的相同元素。

ArrayList<JAXBElement<String>> arrayList = 
        new ArrayList<JAXBElement<String>>(list);

然而,一般来说,您不需要执行任何此操作:只要有可能,针对接口抽象而不是底层具体类进行编码总是更好。

You can't change the fact that the API generates a List.

However, assuming that the underlying implementation actually produces an ArrayList you can always just cast it to an ArrayList:

ArrayList<JAXBElement<String>> arrayList = 
        (ArrayList<JAXBElement<String>>) list;

Or if it isn't an arraylist (i.e. you get an exception trying the above...), you can generate a new ArrayList containing the same elements of the list.

ArrayList<JAXBElement<String>> arrayList = 
        new ArrayList<JAXBElement<String>>(list);

In general however, you shouldn't need to do any of this: it's always better to code against an interface abstraction rather than the underlying concrete class whenever you can.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文