根据here,List<E>.toArray()
方法返回Object[]
。除非您使用T[]
,否则它无法返回<T> T[] toArray(T[] a)
。为什么不能返回E[]
,因为我们将其声明为List<E>
?
答案 0 :(得分:1)
长话短说:类型擦除(以及向后兼容性,在某种程度上)。
Java的泛型以一种相当有趣的方式实现 - 它们只存在于编译阶段,它们用于类型检查。然后在名为 type erasure 的过程中删除它们,其中每个泛型类型的上限(Object
替换为无界类型,例如List<E>
(注意:那里)有一些例外,但在这种情况下这些并不重要)
因此,在运行时,泛型类实际上并不知道泛型类型应该表示的对象的确切类型。因此,List<E>
的实现仅知道它们包含Object
类型的对象,而不是类型E
。
因此,toArray()
实际上不可能返回E[]
,因为执行此类操作所需的信息在运行时是不可用的。这就是toArray(T[])
存在的原因 - T[]
只能在运行时提供所需的类型信息时返回 - 在这种情况下,通过提供的数组,因为数组保持类型的知识他们持有。
此外,我怀疑向后兼容性是返回Object[]
的部分原因。自从引入了Collections API(我认为是1.2或1.3)之后,List
已经出现了,这是在引入泛型之前(1.5)。因此,没有E[]
返回,因为尚未存在的返回机制。因此,对于API稳定性和向后兼容性,保留了Object[]
返回类型。
我认为将Object[]
更改为E[]
不会破坏任何正常工作的代码,因为数组是协变的,但我并不完全相信会是这样的。
答案 1 :(得分:-1)
ArrayList
将对象存储在数组中。调用toArray()
会返回该数组的副本。
实施是:
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
此处elementData
为:
private transient Object[] elementData;
这是ArrayList
存储数据的对象数组。
要返回T[]
,您需要使用toArray(T[] a)
。您只需传递一个类型为T的新数组。
这是ArrayList
中的实施:
public <T> T[] toArray(T[] a) {
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
如果LinkedList
此方法创建Object[]
,则从头开始迭代所有节点,并将元素复制到该数组中。以下是实施:
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Entry<E> e = header.next; e != header; e = e.next)
result[i++] = e.element;
return result;
}
否定选民请发表评论。