java Generics遗留兼容性问题

时间:2009-07-23 03:33:49

标签: java generics

此代码编译良好,并在执行时生成“004b”,为什么它不会产生classcastException。

public static void append(List list) {
    list.add("004b");
}

public static void main(String[] args) {
    List<Integer> intList = new ArrayList<Integer>();
    append(intList);
    System.out.println(intList.get(0));
}

4 个答案:

答案 0 :(得分:4)

建议:

  1. 不要混合原始和通用打字
  2. 打开Java编译器的泛型类型 警告。这将告诉你有关不健全的代码。
  3. 如果使用“已检查集合”类型(例如,使用Collections.checkedList(...)创建),则在将错误键入的对象插入集合时会出现异常。

答案 1 :(得分:3)

您正在调用System.out.println(Object)覆盖,因为intList.get(0)的类型为Integer且没有Integer特定的重载。在编译之后,类型信息被擦除,在类型擦除之后为Object留下仅intList.get(0)的返回类型。这匹配println(Object)函数调用的预期类型,因此没有完成运行时转换,也没有抛出异常。

答案 2 :(得分:2)

因为泛型是通过类型擦除在Java中实现的;也就是说,没有关于类型的运行时信息,只是适当的强制转换。如果你要说

Integer i = intList.get(0);

然后它将编译为

Integer i = (Integer) intList.get(0);

并抛出一个类强制转换异常。

由于System.out.println()将Object作为参数,因此不需要进行转换。

答案 3 :(得分:1)

您希望ClassCastException发生在哪里?

调用append时不会发生这种情况,因为append使用原始List。

调用println时不会发生这种情况,因为println接受一个Object,因此不会进行隐式转换。

重载决策选择println(Object)而不是println(int)可能有点令人惊讶(因为该重载确实存在)。这是因为自动装箱在解决过载时具有非常低的优先级(主要是为了向后兼容)。