Java 为什么收集<;E>#toArray()是否返回E[]?

Java 为什么收集<;E>#toArray()是否返回E[]?,java,arrays,generics,collections,Java,Arrays,Generics,Collections,为什么(非参数化方法)返回对象[] 这是一个有意识的决定吗?如果toArray()方法想要返回E[],那么它为什么不能返回一个E[]。将其与toArray(T[]array)进行对比,后者具有以下源代码(示例来自LinkedList)。请注意,传入的数组不仅用作可能的容器,还可能用于实例化该类型的新数组。如果T不是E的超类,则此代码引发异常;如果无法将对象添加到数组中 @SuppressWarnings("unchecked") public <T> T[] toArray(T[]

为什么(非参数化方法)返回
对象[]


这是一个有意识的决定吗?如果
toArray()
方法想要返回
E[]
,那么它为什么不能返回一个
E[]
。将其与
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;
}
@SuppressWarnings(“未选中”)
公共T[]toArray(T[]a){
如果(a.长度<尺寸)
a=(T[])java.lang.reflect.Array.newInstance(
a、 getClass().getComponentType(),大小);
int i=0;
对象[]结果=a;
for(节点x=first;x!=null;x=x.next)
结果[i++]=x项;
如果(a.长度>尺寸)
a[size]=null;
返回a;
}

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

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

因为列表不知道它的泛型类型,所以它只能创建对象[]

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

    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不知道在运行时要创建什么特定的数组类型

类型擦除是原因。java在运行时不知道T是什么,因此无法创建适当类型的数组。toArray的另一个“类型安全”变体需要一个具有正确类型(在编译时固定!)的“原型”数组,它可以复制。这是历史性的。该方法早于泛型,并保持其现有形式以避免破坏遗留代码。对此我不太确定。我看不出任何方法可以在该方法中获得
E
类。的可能重复。请忽略我投票时的帖子-我粘贴了错误的链接。