在實際開發過程當中咱們常常使用asList講數組轉換爲List,這個方法使用起來很是方便,可是asList方法存在幾個缺陷:java
使用8個基本類型數組轉換爲列表時會存在一個比較有味的缺陷。先看以下程序:apache
public static void main(String[] args) { int[] ints = {1,2,3,4,5}; List list = Arrays.asList(ints); System.out.println("list'size:" + list.size()); } ------------------------------------ outPut: list'size:1
程序的運行結果並無像咱們預期的那樣是5而是逆天的1,這是什麼狀況?先看源碼:數組
public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
asList接受的參數是一個泛型的變長參數,咱們知道基本數據類型是沒法泛型化的,也就是說8個基本類型是沒法做爲asList的參數的, 要想做爲泛型參數就必須使用其所對應的包裝類型。可是這個這個實例中爲何沒有出錯呢?由於該實例是將int 類型的數組當作其參數,而在Java中數組是一個對象,它是能夠泛型化的。因此該例子是不會產生錯誤的。dom
實際上:a.size() debug過來是 [[1, 2, 3, 4, 5]]工具
既然例子是將整個int 類型的數組當作泛型參數,那麼通過asList轉換就只有一個int 的列表了。以下:spa
public static void main(String[] args) { int[] ints = {1,2,3,4,5}; List list = Arrays.asList(ints); System.out.println("list 的類型:" + list.get(0).getClass()); System.out.println("list.get(0) == ints:" + list.get(0).equals(ints)); } -------------------------------------------- outPut: list 的類型:class [I list.get(0) == ints:true
從這個運行結果咱們能夠充分證實list裏面的元素就是int數組。弄清楚這點了,那麼修改方法也就一目瞭然了:將int 改變爲Integer。debug
public static void main(String[] args) { Integer[] ints = {1,2,3,4,5}; List list = Arrays.asList(ints); System.out.println("list'size:" + list.size()); System.out.println("list.get(0) 的類型:" + list.get(0).getClass()); System.out.println("list.get(0) == ints[0]:" + list.get(0).equals(ints[0])); } ---------------------------------------- outPut: list'size:5 list.get(0) 的類型:class java.lang.Integer list.get(0) == ints[0]:true
>>>>>>Java細節(2.1):在使用asList時不要將基本數據類型當作參數。code
對於上面的實例咱們再作一個小小的修改:對象
public static void main(String[] args) { Integer[] ints = {1,2,3,4,5}; List list = Arrays.asList(ints); list.add(6); }
該實例就是講ints經過asList轉換爲list 類別,而後再經過add方法加一個元素,這個實例簡單的不能再簡單了,可是運行結果呢?打出咱們所料:繼承
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(Unknown Source) at java.util.AbstractList.add(Unknown Source) at com.chenssy.test.arrayList.AsListTest.main(AsListTest.java:10)
運行結果盡然拋出UnsupportedOperationException異常,該異常表示list不支持add方法。這就讓咱們鬱悶了,list怎麼可能不支持add方法呢?難道jdk腦殼堵塞了?咱們再看asList的源碼:
public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
asList接受參數後,直接new 一個ArrayList,到這裏看應該是沒有錯誤的啊?別急,再往下看:
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable{ private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { if (array==null) throw new NullPointerException(); a = array; } //................. }
這是ArrayList的源碼,從這裏咱們能夠看出,此ArrayList不是java.util.ArrayList,他是Arrays的內部類。該內部類提供了size、toArray、get、set、indexOf、contains方法,而像add、remove等改變list結果的方法從AbstractList父類繼承過來,同時這些方法也比較奇葩,它直接拋出UnsupportedOperationException異常:
public boolean add(E e) { add(size(), e); return true; } public E set(int index, E element) { throw new UnsupportedOperationException(); } public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); }
經過這些代碼能夠看出asList返回的列表只不過是一個披着list的外衣,它並無list的基本特性(變長)。該list是一個長度不可變的列表,傳入參數的數組有多長,其返回的列表就只能是多長。因此:
>>>>>>Java細節(2.2):不要試圖改變asList返回的列表,不然你會自食苦果。
若是想根據數組獲得一個新的正常的list,固然可能夠循環一個一個添加,也能夠纔有如下2個種方法:
ArrayList<Integer> copyArrays=new ArrayList<Integer>(Arrays.asList(i)); //這樣就是獲得一個新的list,可對其進行add,remove了 copyArrays.add(222);//正常,不會報錯 Collections.addAll(new ArrayList<Integer>(5), i); //或者新建一個空的list,把要轉換的數組用Collections.addAll添加進去
若是你想直接根據基本類型的數組如int[],long[]直接用asList轉成list,那麼咱們能夠選擇用apache commons-lang工具包裏的數組工具類ArrayUtils類的toObject()方法,很是方便,以下:
Arrays.asList(ArrayUtils.toObject(i)); //上邊的代碼:int i[]={11,22,33};達到了咱們想要的效果
這個類功能很強大:
還能「逆向」轉過來,具體就不說了。