对java中的泛型和反射的限制
我正在阅读关于泛型及其限制的内容。
无法创建类型参数的实例
您不能创建类型参数的实例。 例如,下面的代码会导致编译时错误:
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来编译它)。
提前致谢!
正如你所指出的那样,类型参数E
只是编译器使用的东西,它不是用泛型实例化的,不能在运行时使用。 另一方面,参数cls
是真实的。 它是一个运行时传入的对象,其所有类型的信息都将被反映出来。 在cls
类型中的E
(回忆Class<E> cls
)将被类型擦除(毕竟, Class
只是另一个通用类型),但是对象cls
将继承关于它的类型的信息。
这将起作用,因为调用该方法的程序员必须将Class<E>
实例作为参数传递(此类型的实例在类型擦除前将在编译时检查)。 这个实例可以在运行时调用正确的构造函数,因为它可以确定它的运行时类型,如果没有第一个片段中的实际实例,这是不可能的。