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

Posted

技术标签:

【中文标题】Java:将对象转换为泛型类型【英文标题】:Java: Casting Object to a generic type 【发布时间】:2010-11-12 22:57:18 【问题描述】:

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

【问题讨论】:

第二行会产生警告,因为只有泛型会产生这样的警告。第一个不包含泛型,因此没有警告。 【参考方案1】:

这是因为由于类型擦除,在执行时不会真正检查对象是否为List&lt;Integer&gt;。它实际上只是将其转换为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。

【讨论】:

【参考方案2】:

Jon 的答案是正确的,但有时您无法避开该警告(例如,当您使用旧版 API 时)。在这些情况下,您可以像这样抑制警告:

@SuppressWarnings("unchecked")
List<Integer> list = (List<Integer>) someApiThatReturnsNonGenericList();

【讨论】:

【参考方案3】:

为了清楚起见,让我稍微重写一下例子……

我想说,关键的区别

void a(Object o) 
  Integer i = (Integer) o;
  ...

void a(Object o) 
  List<Integer> list = (List<Integer>) o;
  ...

是,鉴于存在类型错误,第一次强制转换在执行时总是立即抛出 RuntimeException(特别是 ClassCastException)。

而第二个可能不会——只要输入参数 o 是任何类型的List&lt;?&gt;,执行就会继续,尽管不正确演员表。

代码是否会在某处稍后抛出异常,取决于您对列表执行的操作。

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

这就是我的理解,这就是编译器设计者认为警告仅适用于第二种情况的原因。

【讨论】:

第一个不会总是抛出 CastClassException。传入的对象很可能是Integer。第一行可能会抛出异常,就像第二行可能会在 o 不是 List 时抛出异常。 @Hot Licks :是的,这就是为什么我在上面写了“鉴于存在类型错误”——我什至用粗体表示;)

以上是关于Java:将对象转换为泛型类型的主要内容,如果未能解决你的问题,请参考以下文章

将返回值转换为泛型类型

将返回值转换为泛型类型

无法将类型“Int”的值转换为泛型中的预期参数类型“Int”

Java泛型详解

为什么不创建一个Object []并转换为泛型类型?解决方案是什么?

将请求参数转换为泛型类