java - 安全转换 <?将 Response> 扩展到 <Response>

标签 java types casting extends

我有一个 HTTP 执行器类:

Future<? extends Response> future = service.apply(request).toJavaFuture();

现在我想删除 ? extends其中的一部分,因为我不想让它对调用者如此通用。基本上,我想返回 Future<Response> .

从我的角度来看:

x extends y

表示 xy , 和 y不是 x .

这意味着 x可以转换为 y .

在我看来,这可以安全地完成,因为x总是延伸y .

为什么以下内容不安全?


    Future<? extends Response> future = service.apply(request).toJavaFuture();

    Future<Response> futureResponse = (Future<Response>) future;

最佳答案

我想说这是编译器对泛型类型参数的限制。编译器知道您正在参数化该类,但它不知道如何使用它。

你的 Future是数据持有者。您不能将任何内容放入其中,只能从中获取请求。在这种情况下,您的期望是 Future<? extends Response>Future<Response>将以相同的方式运行,因此可以安全地进行转换,这是完全合理的。这两个东西都是请求的提供者。确切的实例可能是子类,但无论我们从 Future 中得到什么肯定会实现Request的方法, 所以这个类型转换看起来应该是安全的。

当您的类不是纯粹的供应商,而是它们正在使用数据时,问题就来了。假设我们向 Future 添加了一个方法设置值:

interface Future<T>
{
    void setValue(T value);
    //...
}

我们有一个 Future<? extends Response>它被创建为 Future<ChildResponse> .当我们类型转换它时 Future<Response> , 我们现在可以调用 setValueResponse ,而在类型转换之前我们需要一个 ChildResponse .这就是 Actor 阵容不安全的原因。

实际上,编译器不够聪明,无法区分这两种情况,因此最好的决定是始终将转换声明为不安全的。即使编译器可以区分,但接口(interface)可能会更改这一事实使问题变得更加复杂 - 假设 Future如上所述进行了更改 - 因此以前安全的类型转换将不再安全。

在这种情况下,我个人觉得抑制警告没有问题。转换就是向编译器断言您拥有它没有的信息,这就是您所处的情况。

关于java - 安全转换 <?将 Response> 扩展到 <Response>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56130764/

相关文章:

c++ - Cuda, device, expression 必须有整型或枚举类型

java - 如何在命令提示符下使用 OpenCv 实用程序

java - 如何从 ArrayList 中同时删除多个项目

java - PDFBox+充气城堡-签名PDF

c++ - C++ 中的名称和类型

java - 方法与接口(interface)原型(prototype)匹配,但不会覆盖

Laravel 属性转换

java - JAVA_HOME 环境变量有什么意义

Haskell 递归和类型错误

java - Instanceof 和 Casting,多态性