在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?顺便说一句,我正在使用RestEasy 1.2.1 GA作为JAX-RS前端. 更新(对于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> 有关更多信息,请参阅 > http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |