以ArrayList为例,toArray方法有有参数和无参数两种形式,无参比较简单,直接list.toArray()可以得到一个新数组,但是类型是Object[],大部分时候我们不需要这种类型的数组,而是需要和List的范型对应,所以toArray(T[] a)会是更好的选择。
ArrayList toArray方法源码
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
Arrays copyOf源码
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
根据源码可以看到,toArray无论是哪个分支,无论是有参无参,最后生成数组的都是System.arraycopy方法。
toArray():elementData本身是个Object[],根据copyOf方法源码得知生成的就是Object[],且长度就是原List长度size(这可能会有一点点空间浪费)。
toArray(T[] a):首先传输指定类型T的数组,如果传输的数组长度小于list长度,直接返回T类型的数组,传入的a数组会被弃用,返回数组是经过空间压缩的;如果传输的数组长度不小于list长度,直接用arraycopy把元素复制到传入的a数组,但是a[size] = null是为什么还没搞懂。。
所以平常使用的时候,toArray(T[] a)中a保证是T类型就可以了,长度不用特意考虑,虽然反射创建数组会稍微慢一些。