在 javax.xml.bind 中使集合通用
在我编写的 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;
}
}
我想重构这些以使用泛型,以便可以在超类中实现样板代码:
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> {}
我如何在超类集合上设置 @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。字符串
。
In a REST server that I've written, I have several collection classes that wrap single items to be returned from my services:
@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;
}
}
I would like to refactor these to use generics so the the boilerplate code can be implemented in a superclass:
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> {}
How do I set the @XmlElement
annotation on the superclass collection? I am thinking of something involving a @XmlJavaTypeAdapter
and reflection, but was hoping for something simpler. How do I create the JAXBContext
? BTW, I am using RestEasy 1.2.1 GA for the JAX-RS front-end.
UPDATE (for Andrew White): Here is code that demonstrates getting the Class
object for the type parameter(s):
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>();
}
Here is the output: java.lang.String
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
反射问题
下面是需要进行的反射测试。我相信类型擦除是防止这种情况发生的原因:
上面的代码将输出如下所示的内容。这是因为“getCollection”方法位于 AbstractCollection 的上下文中,而不是 TestReflection。这是为了确保 Java 二进制文件的向后兼容性:
替代方法
如果集合中的项目将使用 @XmlRootElement 进行注释,那么您可以通过以下方式实现您想要做的事情:
并假设 Person 看起来如下所示:
然后以下演示代码:
将生成:
有关详细信息,请参阅:
Reflection Issue
The following is the reflection test that needs to be made work. I believe type erasure is what is preventing this from happening:
The above code will output what is shown below. This is because the "getCollection" method is in the context of AbstractCollection and not TestReflection. This is to ensure backwards compatibility of the Java binaries:
Alternative Approach
If the items in the collection will be annotated with @XmlRootElement, then you could achieve what you want to do with the following:
And assuming Person looks like the following:
Then the following demo code:
Will produce:
For more information see:
我认为由于类型擦除,您所问的问题是不可能的。任何通用解决方案都会丢失解组所需的容器的“类型”。
I think what you are asking is not possible due to type erasure. Any generic solution would lose the "type" of the container needed for unmarshalling.