Java:将对象转换为泛型类型

时间:2010-11-12 22:57:18

标签: java generics casting

在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>*/

3 个答案:

答案 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<?>,执行就会继续,尽管不正确的演员。

代码是否会在稍后某处抛出异常,取决于您对列表的处理方式。

但无论如何,一个异常可能不会抛出转换的行,而是放在其他地方(这可能是一个难以追踪的错误)或根本没有。

这就是我所理解的,是编译器设计者在第二种情况下认为适当的警告的原因。