为什么这会给出未经检查的投射警告?

时间:2014-01-22 18:43:49

标签: java generics

考虑这个例子:

interface A<T> {}
interface B<T> extends A<T> {
    void run();
}
class Test {
    public void main(String[] args) {
        A<SomeType> a = ...;
        if (a instanceof B)
            ((B<SomeType>) a)    //warning: "Type safety: unchecked cast"
                .run();
    }
}

为什么会给出未经检查的投射警告?有没有办法使这个演员有危险,或者我可以简单地忽略这个警告?

请注意,我无法使用if (a instanceof B<SomeType>),因为这会产生以下编译器错误:

  

无法对参数化类型B&lt; SomeType&gt;执行instanceof检查。使用表格B&lt;?&gt;相反,因为在运行时将删除其他泛型类型信息

而且,如果我使用if (a instanceof B<?>),那仍然会发出相同的警告。

2 个答案:

答案 0 :(得分:4)

当这种情况正常发生时,这意味着演员表 这是一个具体的例子:

import java.util.*;

public class Test {

    public static void main(String args[]) {
        List<String> strings = new ArrayList<String>();
        strings.add("Foo");

        Object o = strings;
        if (o instanceof List) {
            List<Integer> integers = (List<Integer>) o;
            System.out.println("The cast 'worked'");
            Integer firstInteger = integers.get(0); // ClassCastException
        }
    }
}

在执行时,没有List<Integer>这样的东西 - 只有List恰好包含Integer个引用,而List恰好包含String {1}}引用等。因此,对List<Integer>执行的强制执行的唯一执行时检查是 <{1}}。

在您的实际代码中,您有:

List

那是使用原始类型 ...这意味着只是因为你有一个interface B<T> extends A { ... } 的引用也是A<Foo>,它不是需要真正成为B。当你使用原始类型时,所有类型的赌注都是关闭的:)

在您发布的代码中,使用:

B<Foo>

没有有警告,因为如果你真的得到的interface B<T> extends A<T> { ... } A<Foo>,那么它必须是一个B。 (当然,你只能通过另一个不安全的演员表获得B<Foo>,但这意味着问题会在之前发生。)

有关详细信息,请参阅Java Generics FAQ on type erasureraw types

答案 1 :(得分:1)

好的,我说。

我写道:

interface B<T> extends A {

而不是:

interface B<T> extends A<T> {