一.Arrays.asList() 返回的list不能add,remove
Arrays.asList()返回的是List,而且是一個定長的List,所以不能轉換為ArrayList,只能轉換為AbstractList
原因在于asList()方法返回的是某個數組的列表形式,返回的列表只是數組的另一個視圖,而數組本身并沒有消失,對列表的任何操作最終都反映在數組上. 所以不支持remove,add方法的
下面是一段很簡單的測試代碼: ?
public?class?MainFacade?{??public?static?void?main(String[]?args)?{??List<Integer>?list?=?Arrays.asList(1,2,3);??list.add(5);??System.out.print(list.toString());??}??
} ?
不過上面的代碼會throw出一個UnsupportedOperationException這樣的異常 ?
Exception?in?thread?"main"?java.lang.UnsupportedOperationException?at?java.util.AbstractList.add(AbstractList.java:148)?at?java.util.AbstractList.add(AbstractList.java:108)?at?org.popkit.MainFacade.main(MainFacade.java:14)?at?sun.reflect.NativeMethodAccessorImpl.invoke0(Native?Method)?at?sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)?at?sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)?at?java.lang.reflect.Method.invoke(Method.java:606)?at?com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)??
終其原因是Arrays.asList方法返回的ArrayList是繼承自AbstractList同時實現
了RandomAccess和Serializable接口,定義如下: ?
private?static?class?ArrayList<E>?extends?AbstractList<E>??implements?RandomAccess,?java.io.Serializable ?
我們再來看看AbstractList這個類的定義: ?
public?abstract?class?AbstractList<E>?extends?AbstractCollection<E>?implements?List<E>???
這時我們發現AbstractList這個類的set add remove方法定義如下:
public?void?add(int?index,?E?element)?{??throw?new?UnsupportedOperationException();??
}??public?E?set(int?index,?E?element)?{??throw?new?UnsupportedOperationException();??
}??public?E?remove(int?index)?{??throw?new?UnsupportedOperationException();??
}??
現在知道了它throw UnsupportedOperationException異常的原因了。 ?
通過上面的分析,我們知道,其實通過asList方法得到的List是只讀的,那么平時我們怎樣避免這樣的錯誤發生?我們可以采用如下方法:?
List<Integer>?list?=?new?ArrayList<>(Arrays.asList(1,2,3)); ?
二、Arrays.asList()陷阱
代碼如下:?
Java代碼??
public?static?void?main(String[]?args)?{??int[]?data?=?{1,2,3,4,5};??List?list?=?Arrays.asList(data);??System.out.println("列表中的元素數量是:"?+?list.size());??}??
? 注意這里輸出的數量是1,原因是,在Arrays.asList中,其接收的參數原型其實是泛型變長參數來的,而基本類型是不能作為范型的參數,按道理應該使用包裝類型,但這里缺沒有報錯,?
因為數組是可以泛型化的,所以轉換后在list中就有一個類型為int的數組?
Java代碼??
int[]?data?=?{1,2,3,4,5};??List?list?=?Arrays.asList(data);??System.out.println("元素類型:"?+?list.get(0).getClass());??System.out.println("前后是否相等:"+data.equals(list.get(0)));??
? 可以看到,輸出的為元素類型:class [I??
因為jvm不可能輸出array類型,array類型屬于java.lang.reflect包,通過反射訪問?
數組的這個類,編譯時候生成的。所以要改為:?
Java代碼??
Integer[]?data?=?{1,2,3,4,5};??
List?list?=?Arrays.asList(data);??
System.out.println("列表中的元素數量是:"?+?list.size());??
?此外,假如如下代碼:?
Java代碼??
//枚舉,聲明一個星期??
enum?Week{Sun,Mon,?Tue,?Wed,Thu,Fri,Sat}??????
public?static?void?main(String[]?args)?{??//工作日??Week[]?workDays?=?{Week.Mon,?Week.Tue,?Week.Wed,Week.Thu,Week.Fri};??//轉換為列表??List<Week>?list?=?Arrays.asList(workDays);??//增加周六也為工作日??list.add(Week.Sat);??
?注意這里用add會出錯,因為是arrays.aslist中,看代碼可以看到這里返回的?
ArrayList不是原來的傳統意義上的java.util.arraylist了,而是自己工具類的一個?
靜態私有內部類,并沒有提供add方法,要自己實現,所以這里是出錯了,因此,?
除非確信array.aslist后長度不會增加,否則謹慎使用:?
???List<String> abc=Arrays.asList("a","b","c"),因為這樣的長度是無法再add的了?