关于Java中ArrayList类的toArray方法详解

发布时间 2023-06-25 17:11:49作者: rockdow

先上源码:

public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

可以看到ArrayList类的toArray()方法调用了Arrays.copyOf(elementData,size)(其中的elementData是ArrayList类中用来存储对象的数组,size是数组大小),接下来进入其内部:

  public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

发现它又调用了重载的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;
    }

原来它会先创建一个T数组引用copy,之后调用System.arraycopy进行复制(对于普通类型的original数组,System.arraycopy是深复制,否则,是浅复制)。至此,可以下定结论,toArray()方法每次放回的数组引用不同,对于普通类型的ArrayList实例来说,toArray是安全的,但是对于对象类型的ArrayList实例来说,toArray是不安全的,如下所示:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static java.lang.reflect.Proxy.newProxyInstance;

public class A  implements Cloneable{
    public String name;

    public static void main(String[] args) throws CloneNotSupportedException {
        ArrayList<A> objects = new ArrayList<>();
        A a1 = new A();
        a1.name = "1";
        objects.add(a1);
        A[] objects1 = (A[])objects.toArray(new A[0]);
        A[] objects2 = (A[])objects.toArray(new A[0]);
        objects1[0].name = "2";
        System.out.println(objects1[0].name);
        System.out.println(objects2[0].name);
    }
}

 可以看到只修改了objects1[0],但objects2[0]也受影响了。