我有一个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 y
是x
,而y
不是y
。
这意味着x
可以强制转换为x
。
在我眼中,这可以安全地完成,因为y
始终延伸x
。
为什么以下内容不安全?
y
答案 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
。
因此,您尝试进行的投射是不安全的。