我有几个发送请求的方法,应该返回特定类型的响应。所有请求都扩展了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
,如果通用方法send
用ErrorResponseVO
响应,它将不起作用。因此,即使你投了它,你也会遇到运行时错误。
查看代码的语义,我认为ErrorResponseVO
更像是一个特殊的响应,应作为异常返回。如果您使用的是Spring,则可以拦截该异常并使用适当的代码向客户端返回正确的HTTP响应。
希望有所帮助。
那不行。想象一下,提供的T
类型是一个鼠标,你正试图用鼠标制作新的猫。您无法定义编译时提供的类型。如果你想避免强制转换,可以考虑在你的方法中添加ErrorResponseVO
对象,并在finally
为responseVO
时将其保存在null
子句中。有很多方法,这只是命题。