在泛型方法中处理类型创建

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在泛型方法中处理类型创建相关的知识,希望对你有一定的参考价值。

我有几个发送请求的方法,应该返回特定类型的响应。所有请求都扩展了RequestVO类型,并且所有响应都扩展了ResponseVO。

为了避免在每个返回响应的方法中进行强制转换,我使用了泛型方法(参见下面的send方法)。

发送每个请求后,即使失败,我也需要在数据库中保存响应。

问题出在responseVO = new ErrorResponseVO(e);,它会产生编译错误:Type mismatch: cannot convert from ErrorResponseVO to T

如何不进行铸造,我该如何避免?

@Override
public AuthSignResponseVO authenticate(AuthRequestVO authRequestVO) throws RegulationException{
    return send(authRequestVO, AuthSignResponseVO.class);

}

@Override
public AuthSignResponseVO sign(SignRequestVO signRequestVO) throws RegulationException{
    return send(signRequestVO, AuthSignResponseVO.class);

}

@Override
public CollectResponseVO collect(CollectRequestVO collectRequestVO) throws RegulationException{
    return send(collectRequestVO, CollectResponseVO.class);

}

@Override
public CancelResponseVO cancel(CancelRequestVO cancelRequestVO) throws RegulationException{
    return send(cancelRequestVO, CancelResponseVO.class);

}

private <T extends ResponseVO> T send(RequestVO requestVO, Class<T> responseType) throws RegulationException{
    HttpHeaders headers = new HttpHeaders();
    HttpEntity<RequestVO> httpEntity = new HttpEntity<>(requestVO,headers);
    ResponseEntity<T> responseEntity = null;
    T responseVO = null;
    try{
        responseEntity = restTemplate.postForEntity(url, httpEntity, responseType);
        responseVO = responseEntity.getBody();
    }catch(RestClientException e){
        responseVO = new ErrorResponseVO(e);
        throw new RegulationException(RegulationResponseCode.GeneralError);
    }finally{
        //save in db the response
    }
    return responseVO;
}
答案

“如果没有施法,我怎么能避免这种情况?”你不能。

用户代码可以在调用方法时指定任何T。所以你必须施展。

另一答案

您的问题实际上是实例化泛型类型,可以在这里找到解释:Instantiating generic objects in Java

所以请尝试以下方法:

responseVO = responseType.getConstructor(RestClientException.class).newInstance(e);
另一答案

要理解编译错误的原因,让我用单词翻译泛型方法的语义。方法send说,给我一个类型,当我被调用时你应该将它作为一个响应。在该描述中,ErrorResponseVO不是签名中指定的调用者的类型。 Java编译器遵循相同的基本原理,因此它不允许分配操作发生,因为它违反了推断类型T

获取编译错误的另一个原因是正确的行为是您在上面定义的特定方法。在像cancel这样的方法中,响应类型应该是CancelResponseVO,如果通用方法sendErrorResponseVO响应,它将不起作用。因此,即使你投了它,你也会遇到运行时错误。

查看代码的语义,我认为ErrorResponseVO更像是一个特殊的响应,应作为异常返回。如果您使用的是Spring,则可以拦截该异常并使用适当的代码向客户端返回正确的HTTP响应。

希望有所帮助。

另一答案

那不行。想象一下,提供的T类型是一个鼠标,你正试图用鼠标制作新的猫。您无法定义编译时提供的类型。如果你想避免强制转换,可以考虑在你的方法中添加ErrorResponseVO对象,并在finallyresponseVO时将其保存在null子句中。有很多方法,这只是命题。

以上是关于在泛型方法中处理类型创建的主要内容,如果未能解决你的问题,请参考以下文章

在泛型方法中返回原始集合类型

在泛型方法中返回特定类型,具体取决于运行时没有反射或动态的枚举值

通过在运行时在泛型方法中进行类型转换来使用递归函数

java在泛型方法中使用它(继承)

详解C#泛型

涉及泛型对象的泛型属性的赋值无法在泛型函数中正确进行类型检查