【问题标题】:Why the Java Compiler does not identify the generic parameter type and indirectly asking to cast?为什么 Java 编译器不识别泛型参数类型并间接要求强制转换?
【发布时间】:2018-03-27 17:13:14
【问题描述】:

我正在编写一个通用方法来处理通用接口的请求类型并返回通用响应。

以上是我的接口、方法和 Pojos。

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();
}

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

【问题讨论】:

  • T 不一定是MyResponse
  • 尝试将buildResponse的返回类型更改为Response
  • 如果SRequest 的某个子类型,但不是MyRequest,或TResponse 的子类型,但不是MyResponse,您将收到ClassCastException。

标签: java generics


【解决方案1】:

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

例如,如果您调用

MyOtherResponse myOtherResponse = this.<MyOtherResponse, MyRequest>handle(request);

地点:

public static class MyOtherResponse implements Request {
    //SomeFields
}

您将返回 MyRequest 而不是 MyOtherResponse,后者会抛出 ClassCastException

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

public <S extends Request> MyResponse handle(S request)

另一方面,如果您可以返回 Response 的不同子类,那么您不能使用该 buildResponse 方法,相反您也可以在该方法中使用泛型(可能会收到 Class&lt;T&gt;),并构造必要的实例.

【讨论】:

    【解决方案2】:

    buildResponseMyRequest 作为参数并返回MyResponse

    但是,您传递给handle 的内容可以是any(任何子类)Request,返回的内容可以是any Response

    即使您将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) 
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-28
      • 2020-06-30
      • 1970-01-01
      • 2016-12-02
      • 1970-01-01
      • 1970-01-01
      • 2016-07-12
      • 1970-01-01
      相关资源
      最近更新 更多