標籤:int ring class 建構函式 origin 總結 類型 row pointer
在看ArrayList源碼時,發現了這樣一行代碼
c.toArray might (incorrectly) not return Object[] (see 6260652)
意思是c.toArray()不一定會返回 Object[] ,請查看編號為6260652的Java Bug
這裡附上Java Bug 網址: Java Bug Database,可以根據關鍵詞或bug id 查詢詳細資料
看一組執行個體吧...
package com.kristin.java;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/** * @author hang li * @since 2018/4/20 */public class DailyTest { public static void test1() { System.out.println("this is test1..."); List<String> list = new ArrayList<>(); list.add("aa"); list.add("bb"); Object[] arr = list.toArray(); System.out.println(arr.getClass().getCanonicalName()); arr[0] = new Object(); DailyTest.printArr(arr); } public static void test2() { System.out.println("this is test2..."); List<String> list = Arrays.asList("aa", "bb"); Object[] arr = list.toArray(); System.out.println(arr.getClass().getCanonicalName()); arr[0] = new Object(); DailyTest.printArr(arr); } public static void test3() { System.out.println("this is test3..."); Object[] arr = new String[]{"aa", "bb"}; arr[0] = 1; DailyTest.printArr(arr); } public static void printArr(Object[] arr) { for (Object o : arr) { System.out.print(o + " "); } System.out.println(); } public static void main(String[] args) { /* 分別依次調用以下三個函數*/ /* * test1 Output: * this is test1... * java.lang.Object[] * [email protected] bb */ DailyTest.test1(); /* * test2 Output: * this is test2... * java.lang.String[] * Exception in thread "main" java.lang.ArrayStoreException: java.lang.Object */ DailyTest.test2(); /* * test3 Output: * this is test3... * Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer */ DailyTest.test3(); }}
test1(),test2()都是調用toArray(),為什麼一個更改arr[0]沒問題,另一個報錯呢?
首先看ArrayList.java中toArray()源碼:由於ArrayList中elementData類型為Object[],所以調用copyOf()傳回值類型為Object[]
public Object[] toArray() { return Arrays.copyOf(elementData, size); }public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); }
再看一下Arrays.asList()源碼及相關代碼: asList()將String[]作為參數傳入,然後調用了ArrayList的代參建構函式,此時a的真實類型依然是String[],然後調用clone(),a的類型依然是String[],所以最終調用了toArray()後,返回的是String[],這也就是為什麼再講數組第一個賦為new Object()時,因為類型不同所以不能進行轉換,這與test3()的例子相似
public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }ArrayList(E[] array) { a = Objects.requireNonNull(array); }public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; }public Object[] toArray() { return a.clone(); }
總結:
由於Arrays.asList()返回的不一定是Object[],所以會出現向數組中添加Object對象報異常的問題,問題是在2005年提出的,現在已經解決了,所以盡量使用toArray(T[] a)避免Exception的發生
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; }
Bug詳情可以參考: OpenJDK
本文參考:
https://www.cnblogs.com/zhizhizhiyuan/p/3662371.html
https://www.zhihu.com/question/66518325/answer/243761796
Java Bug--官方編號為 6260652