考虑这个例子:
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<?>)
,那仍然会发出相同的警告。
答案 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 erasure和raw types。
答案 1 :(得分:1)
好的,我说。
我写道:
interface B<T> extends A {
而不是:
interface B<T> extends A<T> {