Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在泛型方法中处理类型创建_Java_Generics_Casting - Fatal编程技术网

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

Java 在泛型方法中处理类型创建,java,generics,casting,Java,Generics,Casting,我有几个方法可以发送请求并返回特定类型的响应。所有请求扩展RequestVO类型,所有响应扩展ResponseVO 为了避免在每个返回响应的方法中强制转换,我使用了泛型方法(参见下面的send方法) 在发送每个请求之后,即使它失败了,我也需要将响应保存在数据库中 问题在于responseVO=新的ErrorResponseVO(e),它会产生编译器错误:类型不匹配:无法从ErrorResponseVO转换为T 我如何在不施法的情况下避免这种情况 @Override public AuthSign

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

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

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

问题在于
responseVO=新的ErrorResponseVO(e),它会产生编译器错误:
类型不匹配:无法从ErrorResponseVO转换为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;
}
@覆盖
公共AuthSignResponseVO身份验证(AuthRequestVO AuthRequestVO)引发RegulationException{
返回发送(authRequestVO、AuthSignResponseVO.class);
}
@凌驾
公共AuthSignResponseVO签名(SignRequestVO SignRequestVO)引发RegulationException{
返回发送(signRequestVO、AuthSignResponseVO.class);
}
@凌驾
公共CollectResponseVO collect(CollectRequestVO CollectRequestVO)引发RegulationException{
返回发送(collectRequestVO、CollectResponseVO.class);
}
@凌驾
public CancelResponseVO cancel(CancelRequestVO CancelRequestVO)抛出RegulationException{
返回发送(cancelRequestVO、CancelResponseVO.class);
}
private T send(RequestVO RequestVO,Class responseType)抛出RegulationException{
HttpHeaders=新的HttpHeaders();
HttpEntity HttpEntity=新的HttpEntity(请求VO,标题);
ResponseEntity ResponseEntity=null;
T responseVO=null;
试一试{
responseEntity=restTemplate.postForEntity(url、httpEntity、responseType);
responseVO=responseEntity.getBody();
}捕获(RestClientException e){
responseVO=新错误responseVO(e);
抛出新的RegulationException(RegulationResponseCode.GeneralError);
}最后{
//将响应保存在db中
}
返回响应;
}
“不施法我怎么能避免这种情况?”你不能


调用方法时,用户代码可以指定任何
T
。因此您必须强制转换。

您的问题实际上是实例化泛型类型,可以在此处找到解释:

因此,请尝试以下方法:

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

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

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

看看代码的语义,我觉得
ErrorResponseVO
更像是一个异常响应,应该作为异常返回。如果您使用的是Spring,那么您可以截获该异常,并向客户机返回带有正确代码的正确HTTP响应


希望有帮助

那不行。假设提供的类型
T
是一只鼠标,您正试图用鼠标制作一只新的猫。您无法定义编译时提供的类型。如果您想避免转换,请考虑在您的方法中添加<代码> ErrorResponseVO < /Cord>对象并保存在<代码>最后< /COD>子句中,当<代码>响应> > <代码> null < /代码>。有很多方法,这只是一个命题。

如果重新抛出异常,为什么在
catch
中需要返回值?另外,您能否保证
ErrorResponseVO
是可以发送的任何
T
的子类?否则,我认为这段代码不可能工作。Spring
RestTemplate
postForEntity
方法是泛型方法,它希望得到responseType。他们期望如何处理错误?@ErezLevi提供的链接中有解释。首先,泛型在运行时不是真正可访问的。要检查它,您可以创建泛型列表,然后将其用作原始(不带泛型)-您可以将任何对象放在那里,Java不会抱怨。它只会在您尝试使用泛型部分的引用检索对象时发出抱怨,它会告诉您ClassCastException,但我声明
T扩展了ResponseVO
和ErrorResponseVO扩展了ResponseVO。还可能有
AnotherErrorVO
也扩展了
ResponseVO
。如果
T
另一个错误怎么办<代码>
并不意味着像您期望的那样存在多态性行为。阅读更多