为什么Collection<E>.toArray()
(非参数化方法)返回Object[]
?
这是有意识地作出决定吗?如果toArray()
方法无法返回E[]
,是否有任何理由?
答案 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不知道在运行时要创建的特定数组类型。