JAXB:抽象绑定泛型类型的解组失败

时间:2016-08-23 14:56:24

标签: java generics jaxb

如果匹配的Java-Class使用绑定到 abstract 类的泛型类型,我遇到了一个关于使用JAXB解组XML文件的问题。

我已经就这种行为(java.net/jira)提交了一个错误报告,但是我错过了什么或有人有想法解决这个问题?所以这是我的问题:

在下面的示例中,我需要任何类型的Number的边界,但是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());
  }

}

对此有何建议?谢谢!

1 个答案:

答案 0 :(得分:0)

我遇到了一个可能的解决方案(让我们称之为解决方法&#39;解决方法&#39;)以解决我的问题:

@XmlElement T someNumber;更改为@XmlElement(type = Object.class) T someNumber;。这为JAXB提供了可实例化的Object-Class的完全自由......实际上,返回的Value-Object的类型为Double,因此内部转换似乎有效...除了必须注释每个字段 - 任何其他警告呢?