[英]Is this cast in my generic method safe?
我的项目中的代码如下所示:
public interface Bar<T extends Foo<?>> {
//...
}
public class MyFoo implements Foo<String> {
private List<Bar<Foo<String>> barFoo = ...
public <U extends Foo<String>> boolean addBar(Bar<? extends U> b) {
barFoo.add((Bar<Foo<String>>) b); //safe cast?
}
}
Eclipse为addBar
中的addBar
提供了警告,表明addBar
是不安全的。 但是,我是否正确假设投射不会因为我对类型参数施加的限制而抛出,因此投射确实安全?
不一般。
假设Bar
有一个方法void get(T value)
,并且有两个实现Foo<String>
, MyFoo
和YourFoo
。 现在假设调用者在类型为Bar<MyFoo>
的值上调用addBar
。 这有效:当U
= Foo<String>
,我们有Bar<MyFoo>
是Bar<? extends U>
的子类型Bar<? extends U>
Bar<? extends U>
。 现在我们将该值转换为Bar<Foo<String>>
。
现在如果Bar
没有接受T
作为参数的方法,那就没问题了。 但是假设它有一个方法void process(T value)
。 我们调用的实现有T
= MyFoo
,所以它只有一个process(MyFoo value)
方法。 但是,一旦我们将它转换为Bar<Foo<String>>
,我们可能会用YourFoo
调用它。 这是非法的。
在黑暗中刺伤,但我怀疑你真正想做的是将barFoo
声明为List<? extends Bar<? extends Foo<String>>
List<? extends Bar<? extends Foo<String>>
List<? extends Bar<? extends Foo<String>>
。
这不是一个安全的演员。 Eclipse是对的。
想象一下,你有一个扩展Foo
的类MyFoo
,你传入了一个Bar<MyFoo<String>>
现在,当只编译了myMethod(MyFoo x)
签名时, Bar
一些方法带有myMethod(Foo x)
签名,因此方法查找会失败的。
铸造是不安全的,因为虽然U
延伸Foo<String>
,它不是 (必须的),该案Bar<U>
延伸Bar<Foo<String>>
。 事实上, Bar<U>
只会在它们是相同的东西时扩展Bar<Foo<String>>
,即当U
是Foo<String>
。
直觉上,似乎(例如) List<String>
应该是List<Object>
的子类型,但这不是泛型的工作方式。 List<String>
是List<? extends Object>
的子类型List<? extends Object>
List<? extends Object>
,但它不是 List<Object>
的子类型。 (考虑像Comparable<T>
这样的例子可能更有意义: Comparable<String>
意味着“可以与任何String
进行比较,而Comparable<Object>
意味着”可以与任何Object
进行比较。)应该清楚可Comparable<String>
不应该是Comparable<Object>
的子类型。)
[...]演员不会扔[...]因此演员确实安全吗?
我认为你误解了警告的性质。 Eclipse警告你, 即使应该这样做,这个演员也不会抛出,这实际上是为什么它不安全。 例如,这段代码:
final Object o = Integer.valueOf(7);
final String s = (String) o;
是非常安全的,因为演员会抛出异常。 但是这段代码:
final List<?> wildcardList = new ArrayList<Integer>(Integer.valueOf(7));
final List<String> stringList = (List<String>) wildcardList;
是不安全的 ,因为运行时无法检查stringList
(由于擦除),因此它不会抛出异常,即使它是错误的: stringList
现在是一个List<String>
其第一个元素是Integer
类型。 (接下来会发生什么事情,当您尝试对该元素执行某些操作时,您可以获得自发的ClassCastException
。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.