意外的“未经检查的转换”警告

时间:2014-06-20 13:56:39

标签: java generics jdk1.6 unchecked

以下代码会导致未经检查的转换编译器警告 -

{
    List<String> first = first((Class)Integer.class);
}

private <T> List<String> first(Class<T> clazz) { return null; }

但是,以下代码没有任何警告 -

{
    List<String> second = second((Class)Integer.class);
}

private List<String> second(Class<?> clazz) { return null; }

总共有三个警告,前两个我期望,但第三个没有意义 -

$ javac Test1.java -Xlint
    Test1.java:6: warning: [unchecked] unchecked conversion
    found   : java.lang.Class
    required: java.lang.Class<T>
    List<String> first = first((Class)Integer.class);
                               ^
    Test1.java:6: warning: [unchecked] unchecked method invocation: <T>first(java.lang.Class<T>) in Test1 is applied to (java.lang.Class)
    List<String> first = first((Class)Integer.class);
                              ^
    Test1.java:6: warning: [unchecked] unchecked conversion
    found   : java.util.List
    required: java.util.List<java.lang.String>
    List<String> first = first((Class)Integer.class);
                              ^
    3 warnings

编译器版本 -

$ javac -version
    javac 1.6.0_45

我的问题是,为什么会发生第三次编译警告?

2 个答案:

答案 0 :(得分:3)

由于您使用预通用(原始)

传递参数
first((Class)Integer.class)

而不是

first((Class<?>)Integer.class)

first的返回类型降级为预通用List而不是List<String>,并且使用List预期List<String>会导致未经检查的转换警告。


Raw Types上的Java文档解释:

  

原始类型显示在遗留代码中,因为许多API类(例如Collections类)在JDK 5.0之前不是通用的。使用原始类型时,您基本上可以获得pre-generics行为 - Box会为您提供对象。 为了向后兼容,允许将参数化类型分配给其原始类型:

     

...

     

但是如果将原始类型分配给参数化类型,则会收到警告:

答案 1 :(得分:1)

我的猜测是,传入原始类型Class(而不是Class<?>Class<Integer>)会使签名中的<T>无效first方法,由于某种原因导致整个方法调用被视为原始调用。因此,它不仅会使<T>无效,还会使返回类型中的<String>无效。