gpt4 book ai didi

java - 在 javax.xml.bind 中创建一个通用集合

转载 作者:搜寻专家 更新时间:2023-11-01 03:44:31 24 4
gpt4 key购买 nike

在我编写的 REST 服务器中,我有几个集合类,它们包装要从我的服务返回的单个项目:

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "person_collection")
public final class PersonCollection {
@XmlElement(name = "person")
protected final List<Person> collection = new ArrayList<Person>();

public List<Person> getCollection() {
return collection;
}
}

我想重构这些以使用泛型,以便样板代码可以在父类(super class)中实现:

public abstract class AbstractCollection<T> {
protected final List<T> collection = new ArrayList<T>();

public List<T> getCollection() {
return collection;
}
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "person_collection")
public final class PersonCollection extends AbstractCollection<Person> {}

如何在父类(super class)集合上设置 @XmlElement 注释?我在想一些涉及 @XmlJavaTypeAdapter 和反射的东西,但我希望有一些更简单的东西。如何创建 JAXBContext?顺便说一句,我正在为 JAX-RS 前端使用 RestEasy 1.2.1 GA。

更新(针对 Andrew White):这是演示获取类型参数的 Class 对象的代码:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;

public class TestReflection
extends AbstractCollection<String> {
public static void main(final String[] args) {
final TestReflection testReflection = new TestReflection();

final Class<?> cls = testReflection.getClass();
final Type[] types = ((ParameterizedType) cls.getGenericSuperclass()).getActualTypeArguments();
for (final Type t : types) {
final Class<?> typeVariable = (Class<?>) t;
System.out.println(typeVariable.getCanonicalName());
}
}
}

class AbstractCollection<T> {
protected List<T> collection = new ArrayList<T>();
}

这是输出:java.lang.String

最佳答案

反射问题

以下是需要进行的反射测试。我相信类型删除是阻止这种情况发生的原因:

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class TestReflection extends AbstractCollection<String> {

private List<Integer> childCollection = new ArrayList<Integer>();


public List<Integer> getChildCollection() {
return childCollection;
}

public static void main(final String[] args) throws Exception {
final TestReflection testReflection = new TestReflection();

final Class<?> cls = testReflection.getClass();
Method method1 = cls.getMethod("getChildCollection", new Class[] {});
System.out.println(method1.getGenericReturnType());

Method method2 = cls.getMethod("getCollection", new Class[] {});
System.out.println(method2.getGenericReturnType());
}

}

上面的代码将输出如下所示的内容。这是因为“getCollection”方法在 AbstractCollection 而不是 TestReflection 的上下文中。这是为了确保 Java 二进制文件的向后兼容性:

java.util.List<java.lang.Integer>
java.util.List<T>

替代方法

如果集合中的项目将使用@XmlRootElement 进行注释,那么您可以通过以下方式实现您想要执行的操作:

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAnyElement;

public abstract class AbstractCollection<T> {

protected List<T> collection = new ArrayList<T>();

@XmlAnyElement(lax=true)
public List<T> getCollection() {
return collection;
}

}

假设 Person 如下所示:

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Person {

}

然后是下面的演示代码:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(PersonCollection.class, Person.class);

PersonCollection pc = new PersonCollection();
pc.getCollection().add(new Person());
pc.getCollection().add(new Person());

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(pc, System.out);
}

}

将产生:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person_collection>
<person/>
<person/>
</person_collection>

有关详细信息,请参阅:

关于java - 在 javax.xml.bind 中创建一个通用集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5391486/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com