Java中能否获取ArrayList内对象类型实例化泛型类解决JAXB序列化问题
解决方案
核心前提说明
Java泛型采用类型擦除机制实现,泛型参数仅在编译期生效,无法将运行时获取的Class对象直接作为泛型参数写在尖括号中,你示例中的ListConverterAdapter<classType>写法本身不符合Java语法规则。
具体修改方案
1. 调整Base项目中的ListConverterAdapter实现
给列表字段添加@XmlAnyElement(lax = true)注解,无需在Base项目中提前声明所有可序列化类型,JAXB遇到带@XmlRootElement注解的对象时会自动完成序列化/反序列化:
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays", name = "ListOfValuesOfAnyTypeAdapter") public class ListConverterAdapter<E> { @XmlAnyElement(lax = true) @XmlElement(namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays", name = "ListOfValuesOfAnyType") List<E> map; public ListConverterAdapter() { map = new ArrayList<>(); } public ListConverterAdapter(List<E> value) { this.map = value == null ? new ArrayList<>() : new ArrayList<>(value); } public List<E> getMap() { return new ArrayList<>(map); } }
2. 在上层模块构建JAXB上下文,规避循环依赖
不需要在Base项目中依赖Contracts项目的类,把JAXB上下文的构建逻辑放到依赖Base的Contracts项目或者上层业务模块中,初始化时传入实际的元素类型即可:
// 该方法写在MyProject.Contracts项目或上层业务模块中,不存在循环依赖问题 public static <T> String serializeList(List<T> list, Class<T> elementType) throws JAXBException { // 初始化JAXB上下文时同时传入适配器和实际元素类型,JAXB可正常识别对应类型 JAXBContext context = JAXBContext.newInstance(ListConverterAdapter.class, elementType); ListConverterAdapter<T> adapter = new ListConverterAdapter<>(list); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); StringWriter writer = new StringWriter(); marshaller.marshal(adapter, writer); return writer.toString(); }
3. 空列表类型处理方案
空列表本身确实无法提取元素类型,直接在调用序列化方法时由上层主动传入对应元素的Class对象即可,上层调用方明确知晓自身要序列化的列表元素类型,不需要Base层做类型推断。
反序列化适配方案
如果需要做反序列化,同样在上层模块调用时传入元素类型即可:
public static <T> List<T> deserializeList(String xml, Class<T> elementType) throws JAXBException { JAXBContext context = JAXBContext.newInstance(ListConverterAdapter.class, elementType); Unmarshaller unmarshaller = context.createUnmarshaller(); ListConverterAdapter<T> adapter = (ListConverterAdapter<T>) unmarshaller.unmarshal(new StringReader(xml)); return adapter.getMap(); }
内容的提问来源于stack exchange,提问作者GameDevAlien
相关产品推荐
相关产品推荐

