繁体   English   中英

我的通用方法中的强制转换是否安全?

[英]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>MyFooYourFoo 现在假设调用者在类型为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>> ,即当UFoo<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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM