在Java中从Object转换为其他类型时,为什么第二行会产生与强制转换相关的警告,但第一行却没有?
void a(Object o) {
Integer i = (Integer) o;
List<Integer> list = (List<Integer>) o;
}
/*Type safety: Unchecked cast from Object to List<Integer>*/
答案 0 :(得分:24)
这是因为类型擦除导致对象在执行时不会被真正检查为List<Integer>
。它真的只是将它投射到List
。例如:
List<String> strings = new ArrayList<String>();
strings.add("x");
Object o = strings;
// Warning, but will succeeed at execution time
List<Integer> integers = (List<Integer>) o;
Integer i = integers.get(0); // Bang!
有关详细信息,请参阅Angelika Langer's Java Generics FAQ,尤其是type erasure section。
答案 1 :(得分:6)
Jon的答案是正确的,但偶尔你无法解决这个警告(比如当你使用遗留API时)。在这些情况下,你可以像这样抑制警告:
@SuppressWarnings("unchecked")
List<Integer> list = (List<Integer>) someApiThatReturnsNonGenericList();
答案 2 :(得分:6)
为清楚起见,让我稍微重写一下这些例子......
我会说,之间存在 :
void a(Object o) {
Integer i = (Integer) o;
...
}
和
void a(Object o) {
List<Integer> list = (List<Integer>) o;
...
}
是,假设存在类型错误,第一次投射将始终在执行时立即抛出 RuntimeException(特别是ClassCastException)。
虽然第二个可能没有 - 只要输入参数o是任何类型的List<?>
,执行就会继续,尽管不正确的演员。
代码是否会在稍后某处抛出异常,取决于您对列表的处理方式。
但无论如何,一个异常可能不会抛出转换的行,而是放在其他地方(这可能是一个难以追踪的错误)或根本没有。
这就是我所理解的,是编译器设计者在第二种情况下认为适当的警告的原因。