为什么Collection <e> #toArray()不返回E []?</e>

时间:2013-02-23 07:17:25

标签: java arrays generics collections

为什么Collection<E>.toArray()(非参数化方法)返回Object[]

这是有意识地作出决定吗?如果toArray()方法无法返回E[],是否有任何理由?

3 个答案:

答案 0 :(得分:6)

这是因为如果不知道类型T,就无法实例化Class<T>类型的数组。将其与toArray(T[] array)进行对比,后者具有以下来源(来自LinkedList的示例)。请注意,传入的数组不仅用作可能的容器,还可以实例化该类型的新数组。如果T不是E的超类,则此代码会引发异常;如果无法将对象添加到数组中。

@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    if (a.length < size)
        a = (T[])java.lang.reflect.Array.newInstance(
                            a.getClass().getComponentType(), size);
    int i = 0;
    Object[] result = a;
    for (Node<E> x = first; x != null; x = x.next)
        result[i++] = x.item;

    if (a.length > size)
        a[size] = null;

    return a;
}

答案 1 :(得分:1)

Java中的泛型是使用称为类型擦除的技术实现的。这意味着泛型类的实例没有关于其泛型类型的任何信息。考虑一下这个

List<String> list = new ArrayList<String>();
list.toArray();

由于list不知道它的泛型类型,因此它只能创建Object []

答案 2 :(得分:0)

数组容器具有关联的项数据类型,在运行时保留。如果构造一个Object数组然后添加字符串,则该对象将无法转换为String []:

    Object[] objArr = new Object[] {"a", "b"};
    String[] strArr = (String[]) objArr; //Produces ClassCastException

您还可以注意到在向数组添加不正确类型的项时,如何在运行时使用此数组属性:

    String[] strArr = new String[] {"a", "b"};
    Object[] objArr = (Object[]) strArr; //Legal this time
    objArr[0] = 15; //Produces ArrayStoreException

通用类型参数在运行时被擦除,因此当您调用toArray()时,JVM不知道在运行时要创建的特定数组类型。