首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >安全铸造<?将Response>扩展到<Response>

安全铸造<?将Response>扩展到<Response>
EN

Stack Overflow用户
提问于 2019-05-14 12:41:18
回答 2查看 231关注 0票数 1

我有一个HTTP执行器类:

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

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

在我看来:

x extends y

这意味着xyy不是x

这意味着x可以被抛给y

在我看来,这是安全的,因为x总是扩展y

为什么以下是不安全的?

代码语言:javascript
复制
    Future<? extends Response> future = service.apply(request).toJavaFuture();

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

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-14 12:44:20

可以为Future<? extends Response>变量分配Future<Response>Future<ResponseSubClass1>Future<ResponseSubClass2>

Future<ResponseSubClass1>实例不能安全地分配给Future<Response>变量,因为这将允许将ResponseSubClass2分配给Future<ResponseSubClass1>

因此,您的尝试转换是不安全的。

票数 1
EN

Stack Overflow用户

发布于 2019-05-14 13:38:31

我想说,这是编译器对泛型类型参数的限制。编译器知道您正在参数化这个类,但是它没有任何上下文来说明如何使用它。

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

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

代码语言:javascript
复制
interface Future<T>
{
    void setValue(T value);
    //...
}

我们有一个Future<? extends Response>,它是作为Future<ChildResponse>创建的。当我们将其转换为Future<Response>时,我们现在可以用Response调用setValue,而在转换之前我们需要一个ChildResponse。这就是为什么演员被认为不安全的原因。

实际上,编译器不够聪明,无法区分这两种情况,所以最好的决定就是始终将强制转换声明为不安全的。即使编译器能够区分这一点,接口也会改变--假设Future如前所述--使得以前安全的转换不再是安全的,这使得问题变得更加复杂。

在这种情况下,我个人认为压制警告会很好。强制转换就是向编译器断言您有它没有的信息,这就是您所处的情况。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56130764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档