Java编译器忽略类型安全性

时间:2012-08-31 10:34:17

标签: java oop generics types type-safety

public class POJO<T> {

    private List<Integer> integer = new ArrayList<Integer>();

    public POJO() {
        integer.add(1);
        integer.add(2);
    }

    public List<Integer> getInteger() {
        return integer;
    }

    public static void main(String[] args) {
        POJO pojo = new POJO();
        List<String> integer = pojo.getInteger(); // No compile error?
        System.out.println(integer); // prints [1, 2]
    }
}

如何编译以下行:

List<String> integer = pojo.getInteger();

如果输入getInteger(),则输入

public List<Integer> getInteger()

3 个答案:

答案 0 :(得分:7)

由于pojo未声明为通用

POJO pojo = new POJO();

编译器假定您在预通用代码中使用它。即在编写代码后添加泛型的地方。所以当你这样做时

List<String> integer = pojo.getInteger(); 

您收到警告而不是错误。

即。如果类型是非泛型的,则关闭所有通用检查,而不仅仅是与您未提供的类型相关的检查。我相信这是为了最大限度地向后兼容。

进行比较。

Map mapOfInteger = new Map(); // no generics
Set<String> entries = map.entrySet(); // gives a warning, not an error.

在此示例中,如果不是通用的,您可能希望Set<Entry<K, V>>成为Set<Entry>,但编译器会回退到将该类视为非泛型Set

答案 1 :(得分:7)

我在JLS 4.8找到了一个参考资料,用来支持@PeterLawrey所说的内容:

  

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

因此,原始POJO对象的所有实例方法都将被删除,包括那些未引用T的{​​{1}}类型的方法,这意味着(JLS 4.6):

  

方法的类型参数(第8.4.4节)和方法的返回类型(第8.4.5节),如果[...]方法的签名被删除,也会进行擦除。

答案 2 :(得分:2)

这是一项未经检查的作业,出于兼容性原因,不会将其视为错误。

请参阅Interoperating with Legacy Code

  

实际上,分配是合法的,但它会生成未经检查的警告。