【问题标题】:Java: Casting Object to a generic typeJava:将对象转换为泛型类型
【发布时间】: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>*/

【问题讨论】:

  • 第二行会产生警告,因为只有泛型会产生这样的警告。第一个不包含泛型,因此没有警告。

标签: java generics casting


【解决方案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 :是的,这就是为什么我在上面写了“鉴于存在类型错误”——我什至用粗体表示;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多