2016-08-23 111 views
3

如果匹配的Java类使用绑定到抽象类的泛型类型,我遇到了有关使用JAXB解编XML文件的问题。JAXB:抽象绑定泛型类型解组失败

我已经提交了关于此行为的错误报告(java.net/jira),但是baybe我错过了某些东西或者某人有想法解决此问题?所以这里是我的问题:

在下面的例子中,我需要任何类型的数字的边界,但JAXB试图通过实例化为Number,这是抽象的解组。 收集边界或将其更改为可实例化类型(如Object)可解决此问题,但会削弱泛型。

以下示例显示了这一点,请参阅包含的注释。删除注释禁用类型边界,该程序将失败。

import java.io.StringReader; 
import java.io.StringWriter; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

public class JaxbTester { 

    /* 
    * AbstractContainer<T> -> works, but misses boundaries 
    * AbstractContainer<T extends Object> -> works, but boundaries are too large 
    * AbstractContainer<T extends Number> -> fails: "Exception in thread "main" javax.xml.bind.UnmarshalException: Unable to create an instance of java.lang.Number" 
    */ 
    static abstract class AbstractContainer<T /* extends Number */> { 

    @XmlElement 
    T someNumber; 

    } 

    @XmlRootElement 
    static class ContainerImpl<T extends Number> extends AbstractContainer<T> { 

    @SuppressWarnings("unused") 
    private ContainerImpl() { 
     // for JAXB 
    } 

    public ContainerImpl(final T someNumber) { 
     this.someNumber = someNumber; 
    } 

    } 

    /** 
    * @param args 
    */ 
    public static void main(final String[] args) throws Exception { 
    final AbstractContainer<Double> containerA = new ContainerImpl<>(42.5); 

    final JAXBContext context = JAXBContext.newInstance(ContainerImpl.class); 

    final Marshaller marshaller = context.createMarshaller(); 
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

    final StringWriter stringWriter = new StringWriter(); 
    marshaller.marshal(containerA, stringWriter); 
    final String xmlString = stringWriter.toString(); 

    System.out.println(xmlString); 

    final Unmarshaller unmarshaller = context.createUnmarshaller(); 
    unmarshaller.setEventHandler(event -> { 
     System.err.println("!! " + event.getMessage() + " - " + event.getLocator() + "\n"); 
     return true; 
    }); 

    final Object unmarshal = unmarshaller.unmarshal(new StringReader(xmlString)); 
    System.out.println("unmarshal: " + unmarshal.toString()); 
    } 

} 

对此有何建议?谢谢!

回答

0

我碰到一个可能的解决方案来(姑且称之为“处理方法”)我的问题:

变化@XmlElement T someNumber;@XmlElement(type = Object.class) T someNumber;。这给JAXB提供了可实例化对象类的完全自由...实际上,返回的值对象类型为Double,所以内部转换似乎正常工作......除了必须注释每个字段之外 - 对此的任何其他注意事项?