我尝试使用JAXB将XML(String)解析为对象,但是我找不到调用创建的方法的方法,因为我不知道如何用BasicRequest<G>指定类SomeRequest G

public class XMLParser {

    public <G extends BaseRequest> BasicRequest<G> xmlToRequest(String xml,
            Class<BasicRequest<G>> t) {
        BasicRequest<G> request = null;
        try {
            JAXBContext context = JAXBContext.instance(t);
            Unmarshaller m = context.createUnmarshaller();
            StringReader reader = new StringReader(xml);
            JAXBElement<BasicRequest<G>> unmarshal = m.unmarshal(new
                StreamSource(reader), t);
            request = unmarshal.getValue();
        } catch (JAXBException ex) {
            //write log
        }
        return request;
    }
}


这是我的课程:

public abstract class BaseRequest {
    protected String version;

    //getter & setter
}




public class SomeRequest extends BaseRequest {
    protected Integer id;

    //getter & setter
}




public class BasicRequest<G extends BaseRequest> {
    protected String user;
    protected G data;

    //getter & setter
}


实际上,所有类都正确地具有JAXB批注。

如果有人可以帮助我,我应该如何调用该方法或更好的定义方法,我将不胜感激。

最佳答案

也许某个精通JAXB的人有一个聪明的以JAXB为中心的解决方案,但是从泛型的角度来看,我不相信有一种方法可以做您想做的事情。封闭的BasicRequest类的类型参数信息在运行时会被删除(请参见Class object of generic class (java)),因此任何表示ClassBasicRequest对象都将简单地反映原始类型。 (相应地,Unmarshaller将无法知道该参数的意图。)

您可以尝试以下解决方案之一:


如果确定Unmarshaller返回的内容符合BasicRequest,则可以将结果转换为JAXBElement<BasicRequest<G>>。强制转换将产生未经检查的强制转换警告(同样由于类型擦除),可以根据需要使用封闭方法上的@SuppressWarnings("unchecked")注释将其取消。
对于可以代替G的每个类,您可以创建一个子类,该子类扩展使用该类参数化的BasicRequest,即:

public class SomeBasicRequest extends BasicRequest<SomeRequest> {
...
}


但是,无法从SomeBasicRequest分配Class<BasicRequest<G>>,因此您必须按如下方式更改方法标题:

public <G extends BaseRequest> BasicRequest<G> xmlToRequest(String xml, Class<? extends BasicRequest<G>> t) {
...
}

08-03 17:50