c.toArray might not return Object[]?

看源碼的時候看見這樣一句註釋:java

c.toArray might not return Object[],在ArrayList構造函數中就是這樣一句數組

public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652),java的一個bug,在bug文檔6260652中。
        if (elementData.getClass() != Object[].class)//雖然elementData 是object[]類型的,可是它指向的類型不必定是Object[],因此還要進行判斷。
            elementData = Arrays.copyOf(elementData, size, Object[].class);
}

就像下面的代碼同樣函數

//經過ArrayList的toArray()傳過來的數組必定是Object[]類型的
List<String> list = new ArrayList<>(Arrays.asList("list"));
System.out.println(list.getClass());//class java.util.ArrayList
Object[] listArray = list.toArray();
System.out.println(listArray.getClass());//class [Ljava.lang.Object;
listArray[0] = new Object();

//可是構造函數接受的參數是Collection<? extends E> c,其中Arrays.asList()是將數組轉換成list集合的一種方法,其知足形參的要求,
可是其內部的toArray()方法卻與ArrayList的不一樣,其沒有保證傳遞出的數組必定是Object[]類型
List<String> asList = Arrays.asList("asList"); System.out.println(asList.getClass());//class java.util.Arrays$ArrayList Object[] asListArray = asList.toArray(); System.out.println(asListArray.getClass());//class [Ljava.lang.String; asListArray[0] = new Object();//! java.lang.ArrayStoreException //這樣就致使了Object[]的引用指向了String[]的狀況,會引發某些問題,以下所示 String[] strings = {new String()}; Object[] objects = strings; objects[0] = new Object();//! java.lang.ArrayStoreException

再來看看ArrayList的方法和Arrays&ArrayList的方法的不一樣:spa

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

//Arrays.class
public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
//在一次調用中根據參數的不一樣,能返回兩種類型的數組,當傳入的第三個參數爲Object[].class的時候,拷貝一份數組將數組類型定爲Object[],就像構造方法使用的.當不是Object[]數組拷貝一份原先相同類型的數組返回,能夠看到使用了T[].
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        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;
    }

//Arrays.class
//這裏的new ArrayList是Arrays的內部類,不是咱們熟知的那個
public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
//Arrays$ArrayList
private final E[] a;//泛型數組

public Object[] toArray() {
            return a.clone();
        }
//到這裏能夠看出若傳遞給public ArrayList(Collection<? extends E> c)構造函數的集合是Arrays$ArrayList,
那麼它返回的數組類型不必定是Object[],須要在 。
if(elementData.getClass() != Object[].class)進行判斷
相關文章
相關標籤/搜索