2

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

这是有意识做出的决定之一吗?如果需要,该方法是否有任何理由toArray()无法返回 a E[]

4

3 回答 3

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;
}
于 2013-02-23T07:26:26.650 回答
1

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

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

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

于 2013-02-23T07:29:31.840 回答
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 不知道在运行时要创建什么特定的数组类型。

于 2013-02-23T07:36:10.637 回答