我只是在查看List界面中定义的方法:
以正确的顺序返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。如果列表适合指定的数组,则返回其中。否则,将使用指定数组的运行时类型和此列表的大小分配新数组。 如果列表适合指定的数组,并且有空余空间(即,数组的元素多于列表),则紧跟集合结尾的数组中的元素将设置为null。仅当调用者知道列表不包含任何null元素时,这在确定列表长度时很有用。
<T> T[] toArray(T[] a);
我只是想知道为什么它以这种方式实现,基本上如果你传递一个长度为&lt;的数组。到list.size(),它只会创建一个新的并返回它。因此,在方法参数中创建新的Array对象是没用的。
此外,如果你使用列表的大小传递一个足够长的数组,如果返回与对象相同的对象 - 返回它真的没有意义,因为它是同一个对象但是为了清晰起见。
问题在于我认为这会促使代码效率稍低,在我看来,Array应该只是接收类并只返回带有内容的新数组。
有没有什么理由不以这种方式编码?。
答案 0 :(得分:6)
357 public <T> T[] toArray(T[] a) {
358 if (a.length < size)
359 // Make a new array of a's runtime type, but my contents:
360 return (T[]) Arrays.copyOf(elementData, size, a.getClass());
361 System.arraycopy(elementData, 0, a, 0, size);
362 if (a.length > size)
363 a[size] = null;
364 return a;
365 }
也许它有运行时类型?
来自wiki:
因此,实例化Java 参数化类的类是 不可能因为实例化 需要调用构造函数, 如果类型是不可用的 未知的。
答案 1 :(得分:5)
正如其他人所说,有几个不同的原因:
答案 2 :(得分:3)
最有可能的是允许您重用数组,因此您基本上避免(相对昂贵的)某些用例的数组分配。另一个小得多的好处是调用者可以稍微更有效地实例化数组,因为toArray()必须使用'java.lang.reflect.Array.newInstance'方法。
答案 3 :(得分:2)
此方法是1.5之前版本的保留。以下是javadoc
的链接当时那是将列表转换为可再生数组的唯一方法。
这是一个模糊的事实,但是虽然您可以在Object []数组中存储任何内容,但您无法将此数组转换为更具体的类型,例如。
Object[] generic_array = { "string" };
String[] strings_array = generic_array; // ClassCastException
看起来效率更高List.toArray()
就是这样,它会创建一个通用的Object
数组。
在Java泛型之前,进行类型安全转移的唯一方法就是拥有这个cludge:
String[] stronglyTypedArrayFromList ( List strings )
{
return (String[]) strings.toArray( new String[] );
// or another variant
// return (String[]) strings.toArray( new String[ strings.size( ) ] );
}
谢天谢地,仿制药让这些阴谋过时了。留下这个方法是为了提供与1.5之前代码的向后兼容性。
答案 4 :(得分:2)
我的猜测是,如果你在调用T
时已经知道toArray(T[])
的具体类型,那么只需声明一个数组而不是List
就更高效了。为您实现调用Arrays.newInstance()
- 在许多情况下,您可以重新使用该数组。
但如果它让你烦恼,那么编写一个实用方法就很容易了:
public static <E> E[] ToArray(Collection<E> c, Class<E> componentType) {
E[] array = (E[]) Array.newInstance(componentType, c.size());
return c.toArray(array);
}
(注意,没有办法编写<E> E[] ToArray(Collection<E> c)
,因为在没有E
对象的情况下,无法在运行时创建Class
数组,也无法获得Class
1}}运行时E
的对象,因为泛型已被删除。)