为什么Java编译器不识别泛型参数类型并间接请求强制转换?

为什么Java编译器不识别泛型参数类型并间接请求强制转换?,java,generics,Java,Generics,我正在编写一个泛型方法,它处理泛型接口类型的请求并返回泛型响应 前面提到的是我的接口、方法和POJO public interface Request { } public interface Response { } public class MyRequest implements Request{ //SomeFields } public class MyResponse implements Response{ //SomeFields } 现在,我正在编写一个请求

我正在编写一个泛型方法,它处理泛型接口类型的请求并返回泛型响应

前面提到的是我的接口、方法和POJO

public interface Request {
}

public interface Response {
}

public class MyRequest implements Request{
   //SomeFields
}

public class MyResponse implements Response{
   //SomeFields
}
现在,我正在编写一个请求处理程序,其中有一个方法

public <T extends Response, S extends Request> T handle(S request) {

        String decoratedMsg = requestDecorator.writeAsJsonifiedString(request);
        sqsAccessor.pushMessage(decoratedMsg,"SomeURL");
        MyRequest myRequest = (MyRequest) request;
        return (T) buildResponse(MyRequest);
    }

private MyResponse buildResponse(MyRequest request) {
   return new MyResponse();
}
公共T句柄(S请求){
String decoratedMsg=requestDecorator.writeAsJsonifiedString(请求);
pushMessage(decoratedMsg,“SomeURL”);
MyRequest MyRequest=(MyRequest)请求;
返回(T)buildResponse(MyRequest);
}
私有MyResponse buildResponse(MyRequest请求){
返回新的MyResponse();
}

上面代码的问题是,我必须在调用私有方法buildResponse时强制转换我的响应,但我只是想知道,在定义T时,我指定T扩展响应,我的私有方法返回实现响应的MyResponse,那么为什么需要强制转换呢?

buildResponse
MyRequest
作为参数,并返回
MyResponse

public <S extends Request> Response handle(S request) 
但是,传递给
句柄的可以是任何(任何子类)
请求
,返回的可以是任何
响应

即使您将
buildResponse
更改为

private Response buildResponse(Request request) {
   return new MyResponse();
}
编译器强制您1将响应转换为
return(T)buildResponse(request)

如果您的方法将返回
Response
的子类,则不需要使用类型参数
T
。相反,您可以将返回类型标记为
Response

public <S extends Request> Response handle(S request) 
公共响应句柄(S请求)


1这将导致未经检查的强制转换,使您的代码非类型安全。

buildResponse
MyRequest
作为参数,并返回
MyResponse

public <S extends Request> Response handle(S request) 
但是,传递给
句柄的可以是任何(任何子类)
请求
,返回的可以是任何
响应

即使您将
buildResponse
更改为

private Response buildResponse(Request request) {
   return new MyResponse();
}
编译器强制您1将响应转换为
return(T)buildResponse(request)

如果您的方法将返回
Response
的子类,则不需要使用类型参数
T
。相反,您可以将返回类型标记为
Response

public <S extends Request> Response handle(S request) 
公共响应句柄(S请求)


1这会导致未经检查的强制转换,使代码非类型安全。

这是因为
T
扩展了
Response
,这意味着
T
可以是Response的任何子类,而不仅仅是
MyResponse
。这里,方法
buildResponse
返回的
MyResponse
不需要与当前的
T
泛型相同的类型

例如,如果你打电话

MyOtherResponse myOtherResponse = this.<MyOtherResponse, MyRequest>handle(request);
您将返回一个
MyRequest
,而不是
MyOtherResponse
,后者将抛出一个
ClassCastException

如果您总是要返回
MyResponse
类,则应将
handle
方法更改为:

public <S extends Request> MyResponse handle(S request)
公共MyResponse句柄(S请求)

另一方面,如果您可以返回
Response
的不同子类,那么您不能使用
buildResponse
方法,相反,您也可以在该方法中使用泛型(可能接收
),并构造必要的实例。

发生这种情况是因为
T
扩展了
Response
,这意味着
T
可以是response的任何子类,而不仅仅是
MyResponse
。这里,方法
buildResponse
返回的
MyResponse
不需要与当前的
T
泛型相同的类型

例如,如果你打电话

MyOtherResponse myOtherResponse = this.<MyOtherResponse, MyRequest>handle(request);
您将返回一个
MyRequest
,而不是
MyOtherResponse
,后者将抛出一个
ClassCastException

如果您总是要返回
MyResponse
类,则应将
handle
方法更改为:

public <S extends Request> MyResponse handle(S request)
公共MyResponse句柄(S请求)

另一方面,如果您可以返回
Response
的不同子类,那么您不能使用
buildResponse
方法,相反,您也可以在该方法中使用泛型(可能接收
),和构造必要的实例。

T
不一定是
MyResponse
。尝试将
buildResponse
的返回类型更改为
Response
。如果
S
Request
的某个子类型,而不是
MyRequest
,则,或
T
一种
Response
的子类型,但不是
MyResponse
,您将得到一个ClassCastException。
T
不一定是
MyResponse
。请尝试将
buildResponse
的返回类型更改为
Response
。如果
S
Request
的某个子类型,而不是
MyRequest
,则,或者
T
一个
Response
的子类型,但除了
MyResponse
,您将得到一个ClassCastException。