当前位置: 首页 > 知识库问答 >
问题:

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

徐经武
2023-03-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,那么为什么需要强制转换呢?

共有2个答案

贺栋
2023-03-14

buildResponse将一个MyRequest作为参数,并返回一个MyResponse

但是,传递给handle的可以是任何(任何子类)请求,返回的可以是任意

即使在将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 这会导致未经检查的转换,使您的代码非类型安全。

郑正文
2023-03-14

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

例如,如果你打电话

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

其中:

public static class MyOtherResponse implements Request {
    //SomeFields
}

您将返回一个< code>MyRequest,而不是一个将引发< code>ClassCastExcepthtml" target="_blank">ion的< code>MyOtherResponse。

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

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

另一方面,如果您可以返回Response的不同子类,那么您就不能使用buildResponse方法,而可以在该方法中使用泛型

 类似资料:
  • 问题内容: 我正在尝试使用泛型实现以下结构。收到编译器错误,无法找出原因。 这个想法是译者使用T作为字典中键的类型。例如,可以是字符串或枚举。子类提供具体的字典。 但是它失败,因为:“类型’String’不符合协议’Hashable’” 但是String符合Hashable。它也不适用于Int,后者也符合Hashable。 如果删除类型约束,则仅用于测试(在此我还必须禁用字典,因为我不能在其中使用

  • 问题内容: 我有以下两节课: 和: 当我运行测试时,一切都是笨拙的。如果我将类型参数化更改为: 编译器抱怨,报告: 错误:类型不兼容的整数不能转换为T number = new Integer(11); 其中T是类型变量T扩展了在方法getSomeValue(boolean)中声明的Object 它同样对Double有所抱怨。为什么? 编辑:我犯了一个错误。这实际上是有效的代码。 现在我明白了@S

  • 我有一个泛型接口,可以由抽象基类的不同子类实现。 在基类中,我定义了一个小的帮助器方法,检查当前实例是否实现了该接口,并在可能的情况下强制转换为该接口: 例如,我使用这个helper方法来获取和打印这些值: 但这会给我一个不安全的强制转换警告,因为现在返回的是而不是。我知道编译代码后泛型类型信息会丢失,但是由于的返回类型总是类型的,所以它应该是安全的? 为什么类型信息首先丢失? 是否可以直接动态强

  • 此代码有效。它以“未检查或不安全操作”警告进行编译和运行。 当这两个给我运行时错误时 我遇到的错误如下:

  • 问题内容: 我正在制作一个类,以便模拟C ++中的函数指针的功能。最初,我只用s 做所有事情,但后来我有了一个想法- 为什么不使其真正通用? 问题出在这个构造函数上,该构造函数试图使用签名调用另一个构造函数: 我以为这会很好,但是我收到了以下编译器错误: 因此,我很困惑,我这样做: 现在可以编译,但是我收到以下警告: 我想问题是我不明白这意味着什么。我认为,由于从参数推断出的类型,因此有 必要 调

  • 我正试图解决一个泛型问题。我在做一些手工选角,感觉好像我做错了什么。我对使用泛型有点陌生,所以很有可能我在某些方面误用了它们。如能提供指导,将不胜感激。 TLDR: 我有一个带有泛型方法的接口,该泛型方法采用参数。我在一个类中实现了这个接口,但在实现器中,我希望确保是特定类型的(假设,这样我就可以提取一些字段)。我怎么能那样做? 详细信息: 下面有一个接口和一个实现类,其中。 具有以下定义: 而具