这两个办法都是将列表 List 中的元素转导出为数组,不同的是,toArray()办法导出的是 Object 类型数组,而 toArray[T[] a]办法导出的是指定类型的数组。
1. toArray()办法
toArray()办法会返回 List 中所有元素形成的数组,并且数组类型是 Object[]。还要留神一点就是,toArray()返回的是一个新的数组对象,并且屡次执行 toArray()办法取得的是不同的数组对象,并且对其中一个数组进行批改,不会影响到其余 toArray()办法取得的数组,并且也不会影响到 list 自身原来存储的元素值.
private static class People{
String name;
public People(String name){this.name = name;}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
'}';
}
}
//People 类和上一个例子中的一样,这里不再列出了。public static void main(String[] args) {List<People> list = new ArrayList<>();
list.add(new People("小明"));
list.add(new People("小王"));
Object[] objects1 = list.toArray();
Object[] objects2 = list.toArray();
System.out.println("objects1 == objects2 :"+(objects1 == objects2));
((People)objects1[1]).name = "小花";
System.out.println("show objects1:"+ Arrays.toString(objects1));
System.out.println("show objects2:"+ Arrays.toString(objects2));
System.out.println("show list:"+list);
}
输入后果:
objects1 == objects2 : false
show objects1: [People{name=‘小明’}, People{name=‘小花’}]
show objects2: [People{name=‘小明’}, People{name=‘小花’}]
show list: [People{name=‘小明’}, People{name=‘小花’}]
从这个例子的输入后果能够看出,对元素对象自身就行批改,会导致 toArray()返回的所有数组中的内容都产生扭转,包含原始的 list 容器外面的元素类容。从这个例子能够得出,如果 list.toArray()返回的数组中寄存的是 list 原始对象的援用,只是创立了一个新的数组来装这些援用,并没有对 list 中原始对象进行拷贝或复制。
ArrayList 中 toArray()的实现源码:
public Object[] toArray() {return Arrays.copyOf(elementData, size);
}
在 ArrayList 中的实现是调用了 Arrays 工具类的 copyOf()办法,这和 ArrayLIst 类中元素的存储构造相干。至于 Arrays.copyOf()办法的作用就是下面剖析的 List 的 toArray()办法的作用了,因为 toArray()实质上就是间接调用的 Arrays.copyOf()办法了。
2、toArray[T[] a]办法
toArray(T[] a)办法应用了泛型参数,能够返回指定类型数组,然而这个泛型在确定的时候必须是 list 中元素类型的父类或自身,至于那个参数数组,其实就是为了传递参数类型罢了
底层源码:
@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;
}
从实现源码中看出,首先会判断数组 a 的长度和 list 元素的个数,进行一个比拟,如果 a 数组的长度小于 list 元素个数,那么就会间接调用工具类 Arrays.copyOf()办法间接进行一个拷贝,留神,这儿的是 Arrays.copyOf(elementData, size, a.getClass())办法,是由元素类型参数的,就是最初一项参数,和 toArray()办法实现 Arrays.copyOf(elementData, size)不雷同。
接着在看,如果数组 a 的长度 length 不小于 list 元素个数,即 a . l e n g t h > = s i z e a.length >= sizea.length>=size 得话,就会走上面的流程,首先调用 System.arraycopy(elementData, 0, a, 0, size)将 ArrayList 里的元素数组 elementData 中的元素拷贝到 a 对象中,至于这个 System.arraycopy()在这里就不具体说了。
接下来会判断一下 a.length 是否大于 list 元素个数 size,如果大于的话,会在 a[size]地位设置一个 null,这个设置的目标是了 toArray(T[] a)办法调用者从返回的数组中检测到 null 时就晓得前面曾经没有 list 元素对象了。
总结
List 接口的 toArray()办法就是间接调用 Arrays.copyOf(elementData, size),将 list 中的元素对象的援用装在一个新的生成数组中。
List 接口的 toArray(T[] a)办法会返回指定类型(必须为 list 元素类型的父类或自身)的数组对象,如果 a.length 小于 list 元素个数就间接调用 Arrays 的 copyOf()办法进行拷贝并且返回新数组对象,新数组中也是装的 list 元素对象的援用,否则先调用 System.arraycopy()将 list 元素对象的援用装在 a 数组中,如果 a 数组还有残余的空间,则在 a[size]搁置一个 null,size 就是 list 中元素的个数,这个 null 值能够使得 toArray(T[] a)办法调用者能够判断 null 前面曾经没有 list 元素了。