使用通用方法处理类型创建

时间:2018-12-20 09:40:24

标签: java generics casting

我有几种发送请求的方法,应该返回特定类型的响应。所有请求都扩展了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;
}

4 个答案:

答案 0 :(得分:0)

“如何在不进行强制转换的情况下避免这种情况?”你不能。

在调用您的方法时,用户代码可以指定任何T。所以你必须投。

答案 1 :(得分:0)

您的问题实际上是实例化泛型,并且可以在此处找到说明: Instantiating generic objects in Java

因此,请尝试尝试以下操作:

responseVO = responseType.getConstructor(RestClientException.class).newInstance(e);

答案 2 :(得分:0)

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

导致编译错误是正确行为的另一个原因是您在上面定义的特定方法。在类似cancel的方法中,响应类型应该为CancelResponseVO,如果通用方法sendErrorResponseVO响应,则响应类型将不起作用。因此,即使您进行强制转换,您也会收到运行时错误。

看一下代码的语义,在我看来ErrorResponseVO更多地是 exception 响应,应作为异常返回。如果您使用的是Spring,则可以拦截该异常,并将正确的HTTP响应和正确的代码返回给客户端。

希望有帮助。

答案 3 :(得分:0)

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