This question already has answers here:
What's the reason I can't create generic array types in Java?
(16个答案)
4年前关闭。
我正在为Java中期学习,但是我对reified类型有一些问题。这里有一个错误的课,但我不明白为什么。有人可以帮我,也许给我一些解释吗?该错误当然与确定类型有关。
但是,您必须记住,这是非常不安全的。仅当创建的箭头的范围较小时才应执行此操作,以便可以手动确保该数组仅包含
在此处标记的行将引发异常,因为您正在尝试将
如果确实需要正确的运行时类型的数组,则需要使用反射。获取所需类型的类型标记(类型为
(16个答案)
4年前关闭。
我正在为Java中期学习,但是我对reified类型有一些问题。这里有一个错误的课,但我不明白为什么。有人可以帮我,也许给我一些解释吗?该错误当然与确定类型有关。
class Conversion {
public static <T> T[] toArray(Collection<T> c) {
T[] a = new T[c.size()];
int i = 0;
for (T x: c) a[i++] = x;
return a;
}
}
最佳答案
数组是一种修饰类型。这意味着在运行时知道数组的确切类型。因此,在运行时,例如String[]
和Integer[]
之间是有区别的。
泛型不是这种情况。泛型是一个编译时构造:它们用于在编译时检查类型,但是在运行时,确切的类型不再可用。在运行时,类型参数只是Object
(或者,如果类型参数有上限,则为上限)。因此,在运行时,Collection<String>
和Collection<Integer>
的类型没有区别。
现在,当您要创建类型参数的数组时出现问题。在运行时未知T
是什么,因此如果编写new T[10]
,则Java运行时将不知道要创建哪种数组,即String[]
或Integer[]
。这就是为什么您不能以这种方式创建数组的原因。
有一些变通办法,没有一个完全令人满意。通常的解决方案是创建一个Object[]
,并将其转换为所需的数组类型:
T[] theArray = (T[]) new Object[size];
但是,您必须记住,这是非常不安全的。仅当创建的箭头的范围较小时才应执行此操作,以便可以手动确保该数组仅包含
T
实例,并且永远不会分配给无法容纳该数组的任何对象。以下代码演示了该问题:public class Foo<T extends Comparable> {
T[] createArray() {
return (T[])new Object[1];
}
public static void main(String... args) {
Foo<String> foo = new Foo<>();
String[] ss = foo.createArray(); // here
}
}
在此处标记的行将引发异常,因为您正在尝试将
Object[]
强制转换为String[]
!如果确实需要正确的运行时类型的数组,则需要使用反射。获取所需类型的类型标记(类型为
Class<T>
),然后使用Array.newInstance(type, cize)
创建数组,例如:public T[] createArray(Class<T> type, int size) {
return (T[]) Array.newInstance(type, size);
}