Java和反射中对泛型的限制

时间:2014-12-21 23:39:57

标签: java generics type-erasure

我正在阅读有关仿制药及其限制的内容。

  

无法创建类型参数的实例

     

您无法创建类型参数的实例。例如,   以下代码导致编译时错误:

public static <E> void append(List<E> list) {
    E elem = new E();  // compile-time error
    list.add(elem);
}
     

作为一种变通方法,您可以创建一个类型参数的对象   反射:

public static <E> void append(List<E> list, Class<E> cls) throws Exception {
    E elem = cls.newInstance();   // OK
    list.add(elem);
}
     

您可以按如下方式调用append方法:

List<String> ls = new ArrayList<>();
append(ls, String.class);

我有点困惑。我理解为什么它不被允许,因为新的E()会因为类型擦除而变成新的object(),但为什么在class.newInstance中不会发生同样的事情?我的意思是它使用类型参数E,所以不会最终出现同样的问题吗?有人可以解释一下(我知道我必须添加try-catch才能让它编译)。

提前致谢!

2 个答案:

答案 0 :(得分:3)

正如您所注意到的,类型参数E只是编译器使用的东西,它不是用泛型实例化的,不能在run-rime中使用。另一方面,参数 cls是真实的。它是在运行时传入的对象,其中包含所有类型信息。 E类型 {召回cls中的Class<E> cls进行类型删除(毕竟,{{1} }只是另一个通用的)但对象 Class将继承有关其类型的信息。

答案 1 :(得分:0)

它将起作用,因为调用该方法的程序员必须将Class<E>实例作为参数传递(此类型的类型将在类型擦除之前的编译时检查)。此实例将能够在运行时调用正确的构造函数,因为它能够确定其运行时类型,如果没有第一个片段中的实际实例,这是不可能的。