为什么在泛型类中使用泛型返回调用方法被javac认为是不安全的?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (25)

考虑下面的代码:

public class Main {
    public static class NormalClass {
        public Class<Integer> method() {
            return Integer.class;
        }
    }

    public static class GenericClass<T> {
        public Class<Integer> method() {
            return Integer.class;
        }
    }

    public static void main(String... args) {
        NormalClass safeInstance = new NormalClass();
        Class<Integer> safeValue = safeInstance.method();

        GenericClass unsafeInstance = new GenericClass();
        Class<Integer> unsafeValue = unsafeInstance.method();
    }
}

如果我编译它:

$ javac -Xlint:unchecked Main.java 

它返回:

Main.java:16: warning: [unchecked] unchecked conversion
        Class<Integer> unsafeValue = unsafeInstance.method();
                                                          ^
  required: Class<Integer>
  found:    Class
1 warning

请注意只有通用方法被认为是不安全的,即使在返回类型中没有引用通用类型。

这是一个javac错误?或者我没有考虑更深层次的原因?

提问于
用户回答回答于

允许原始类型确保与引入泛型之前编写的代码的兼容性。原始类型通过忽略来自所有方法参数和返回类型的所有类型信息,甚至与类的类型参数无关的类型信息而工作。正如你所发现的,这可能会导致奇怪的结果。但它比这更奇怪。例如,这个编译。

public class Main {

    public static class GenericClass<T> {
        public void foo(Class<Integer> clazz) {
        }
    }

    public static void main(String... args) {
        GenericClass unsafeInstance = new GenericClass();
        unsafeInstance.foo(String.class);
    }
}
用户回答回答于

未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.4节,第9.4节)或非静态字段(第8.3节)M的类型是对应的原始类型在对应于C的通用声明中删除它的类型。

Java语言规范

扫码关注云+社区