發現問題 前幾天在看別人的項目的時候,發現一個問題,簡單復現一下這個問題 // 註意這是一個Integer對象的數組哦 Integer[] arr = new Integer[]{9999,88,77}; List<Integer> list = Arrays.asList(arr); // 執行以 ...
發現問題
前幾天在看別人的項目的時候,發現一個問題,簡單復現一下這個問題
// 註意這是一個Integer對象的數組哦
Integer[] arr = new Integer[]{9999,88,77};
List<Integer> list = Arrays.asList(arr);
// 執行以下操作,有問題麽?
list.add(1);
list.remove(0);
好的,如果你覺得沒錯,和我剛開始的想法一致。在我沒有認真學習這個asList方法時,天真的以為沒有問題,顧名思義啊,就是把數組轉換成List唄。
// 恭喜,喜提報錯,如果是這樣測試該找你麻煩了,/(ㄒoㄒ)/~~
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at TestForAsList.main(TestForAsList.java:13)
廢話不多說,我們直接進源碼裡面看看。
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a); // 看起來沒有任何異常,emm。然而呢,這個ArrayList並不是Java.util包下的ArrayList,而是一個在Arrays下實現的內部類。
}
我們發現這個靜態內部類裡面並沒有實現List的add和remove方法。那麼子類將延用父類AbstractList的方法實現,這個繼承應沒有什麼問題。
// 我們進入這個父類的實現,發現了報錯的根源。。
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
}
總結:
究其原因,就是這個asList方法返回的是一個內部類,只實現了一些遍歷以及更新的方法。下次使用它的時候需要註意一下。
擴展知識點
數組值的變化
然後我就發現了這個很有意思的點,就是這個Arrays包下的ArrayList用的是構造器傳進來的數組,並不像我們原來認為的ArrayList的那樣會拷貝數組然後創建一個新的數組。
這意味著我們在對這個List進行set的改動時,我們同時會更改原數組的值。
public static void main(String[] args) {
Integer[] arr = new Integer[]{9999,88,77};
List<Integer> list = Arrays.asList(arr);
list.set(1,0);
System.out.println(list.get(1)); // 輸出0
System.out.println(arr[1]); // 同樣也輸出了0
}
int[]數組
我們都知道int是基本數據類型,如果我們向asList()方法裡面傳入一個int[]數組會發生什麼呢?
我們知道泛型的話需要的是對象類型,基礎數據類型是不能作為泛型的。
// 此時int[]會作為一個對象類型,然後轉換為list。此時長度為1,且可以正常的取出來作為list元素
public static void main(String[] args) {
int[] arr = new int[]{9999,88,77};
List<int[]> list = Arrays.asList(arr);
System.out.println(list.size());
System.out.println(list.get(0)[0]);
System.out.println(list.get(0)[1]);
System.out.println(list.get(0)[2]);
}
好了,asList()方法就學廢了。一天學廢一個小知識/dog