假设你有一个如下定义的数组列表:
ArrayList<String> someData = new ArrayList<>();
稍后在您的代码中,由于泛型,您可以这样说:
String someLine = someData.get(0);
并且编译器完全知道它将得到一个字符串。耶泛型!但是,这将失败:
String[] arrayOfData = someData.toArray();
toArray()
将始终返回一个对象数组,而不是定义的泛型。为什么get(x)
方法知道返回的是什么,而toArray()
却默认是Objects?
最佳答案
如果你看一下 ArrayList<E> 的 toArray(T[] a)
的实现类,是这样的:
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
此方法的问题是您需要传递相同泛型类型的数组。现在考虑如果此方法不带任何参数,那么实现将类似于:
public <T> T[] toArray() {
T[] t = new T[size]; // compilation error
return Arrays.copyOf(elementData, size, t.getClass());
}
但这里的问题是,你不能在 Java 中创建泛型数组,因为编译器不知道 T
到底代表什么。换句话说,创建不可具体化类型的数组(JLS §4.7)在 Java 中是不允许的。
Array Store Exception (JLS §10.5) 的另一个重要引述:
If the component type of an array were not reifiable (§4.7), the Java Virtual Machine could not perform the store check described in the preceding paragraph. This is why an array creation expression with a non-reifiable element type is forbidden (§15.10.1).
这就是为什么 Java 提供了重载版本 toArray(T[] a)
.
I will override the toArray() method to tell it that it will return an array of E.
因此,您应该使用 toArray(T[] a)
,而不是覆盖 toArray()
。
Cannot Create Instances of Type Parameters来自 Java Doc 的内容可能对您来说也很有趣。
关于ArrayList.toArray() 中的 Java 泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36598928/