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

Mik*_*ike 16 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>*/
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 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!
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅Angelika Langer的Java Generics FAQ,尤其是类型擦除部分.


Bra*_*pit 6

Jon的答案是正确的,但偶尔你无法解决这个警告(比如当你使用遗留API时).在这些情况下,您可以像这样抑制警告:

@SuppressWarnings("unchecked")
List<Integer> list = (List<Integer>) someApiThatReturnsNonGenericList();
Run Code Online (Sandbox Code Playgroud)


Rop*_*Rop 6

为清楚起见,让我稍微重写一下这些例子......

我会说,两者之间的关键区别:

void a(Object o) {
  Integer i = (Integer) o;
  ...
}
Run Code Online (Sandbox Code Playgroud)

void a(Object o) {
  List<Integer> list = (List<Integer>) o;
  ...
}
Run Code Online (Sandbox Code Playgroud)

是的,鉴于存在类型错误,第一个强制转换将始终在执行时立即抛出 RuntimeException(特别是ClassCastException).

虽然第二个可能不是 - 只要输入参数o是任何类型List<?>,执行将继续执行,尽管不正确的强制转换.

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

但无论如何,可能不会在构建转换的行上抛出异常,而是在其他地方抛出(可能是难以追踪的错误)或根本不抛出异常.

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