如何使用泛型传递参数:Class <clazz <g>&gt; </clazz <g>

时间:2014-07-08 20:01:35

标签: java xml jaxb generic-programming

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

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注释。

如果有人可以请我帮我说明如何调用该方法或更好的方法来定义它,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

也许精通JAXB的人有一个聪明的以JAXB为中心的解决方案,但从泛型的角度来看,我不相信有办法做你想做的事情。封闭BasicRequest类的类型参数信息在运行时被删除(请参阅Class object of generic class (java)),因此代表Class的任何BasicRequest对象将仅反映原始类型。 (相应地,Unmarshaller将无法知道该参数的用途。)

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

  1. 如果您确定Unmarshaller返回的内容符合BasicRequest,那么您可以将结果转换为JAXBElement<BasicRequest<G>>。演员表将产生未经检查的演员警告(同样,因为类型擦除),如果您愿意,可以使用封闭方法上的@SuppressWarnings("unchecked")注释来抑制。
  2. 对于你可以取代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) {
    ...
    }