1.Arrays类是一个 final 类,其类中含有一个私有的 ArrayList, ArrayList的定义与 java.util.ArrayList中的定义相同。
java源码:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
2. Arrays调用 toArray()时, 调用的是 ArrayList 中数据数组的 clone, 当调用 toArray(T[])时,则使用 System.arraycopy()。
Arrays.java
<span style="font-size:18px;"> <span style="white-space:pre"> </span>@Override
public Object[] toArray() {
return a.clone();
}
@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}</span>
3. ArrayList 则是调用 Arrays.copyof, 再调用Arrays类中的 System.arraycopp。
ArrayList.java
<pre name="code" class="java">public Object[] toArray() {
return Arrays.copyOf(elementData, size);
Arrays.java
<span style="font-size:18px;"> public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}</span>
4. 分析一下运行结果。
<span style="font-size:18px;"><span style="white-space:pre"> </span>@Test
public void test() {
// 使用 Arrays类中 toArray
StringBuilder sb = new StringBuilder("a");
Object[] o = new Object[] {sb, "b", "c"};
Arrays.asList(o).toArray();
System.out.println(sb.toString());
sb.setCharAt(0, 'X');
System.out.println(sb.toString());
// 使用 ArrayList 类中的 toArray
StringBuilder sb2 = new StringBuilder("a");
Object[] o3 = new Object[] {sb2, "b", "c"};
new ArrayList<>(Arrays.asList(o3)).toArray();
System.out.println(sb2.toString());
sb.setCharAt(0, 'X');
System.out.println(sb2.toString());
}</span>
5.结果:a X a a
6. 使用 T 方法时,两个结果都是一样的,因为都是使用 System.arraycopy 方法,而不是使用 clone() 方法。
ArrayList.java
<span style="font-size:18px;">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;
}
</span>
Arrays.java
<span style="font-size:18px;"> public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}</span>
7. 总结
推荐使用带有参数的
toArray(T[] a)
方法,这样就避免了浅克隆带来的问题。