安全地投放<!-?将Response->扩展到<response>

时间:2019-05-14 12:41:19

标签: java types casting extends

我有一个HTTP执行程序类:

Calendar cal = Calendar.getInstance(Locale.ENGLISH); cal.setTimeInMillis(timestamp * 1000L); String date = DateFormat.format("dd-MM-yyyy hh:mm:ss", cal).toString();

现在,我想删除其中的Future<? extends Response> future = service.apply(request).toJavaFuture();部分,因为我不想让它对调用者如此通用。基本上,我想返回? extends

从我的角度来看:

Future<Response>

将表示x extends yx,而y不是y

这意味着x可以强制转换为x

在我眼中,这可以安全地完成,因为y始终延伸x

为什么以下内容不安全?

y

2 个答案:

答案 0 :(得分:2)

我会说,这是编译器在泛型类型参数方面的局限性。编译器知道您正在对类进行参数化,但是它没有任何有关如何使用它的上下文。

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

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

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

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

实际上,编译器不够聪明,无法区分这两种情况,因此最好的决定是始终将强制转换声明为不安全。即使编译器可以区分两者,但由于接口可能发生更改(假设Future如上所述已发生更改),因此问题变得更加复杂,因此以前安全的转换将不再存在。

在这种情况下,我个人会抑制警告。强制转换的全部内容是向编译器断言您所拥有的信息,这就是您所处的情况。

答案 1 :(得分:1)

可以为Club Overall Average = IF ( HASONEVALUE ( data[Club] ), CALCULATE ( AVERAGE ( data[Overall] ), ALL ( data[Name] ), data[Club] = VALUES ( data[Club] ) ), BLANK() ) 变量分配Future<? extends Response>Future<Response>Future<ResponseSubClass1>

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

因此,您尝试进行的投射是不安全的。