以前一直很奇怪為什麼Arrays.asList的數組不能插入新的數據,後來看了源碼發現是因為內部是一個final的數組支持起來的Arraylist,下面貼入源碼與分析。
1.先看Arrays的方法
我們看到Arrays.aslist 返回一個new ArrayList<>(a);
@SafeVarargs public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
2.我們按住ctrl點擊這個ArrayList
發現這個ArrayList不是java.util中的Arraylist而是在Arrays這個類中的一個私有靜態類並且繼承了AbstractList,
這個類中的set和get方法其實是基於private final E[] a 這個泛型數組的;
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; } public E get(int index) {//得到數組中的值 return a[index]; } public E set(int index, E element) {//替換數組中的值 E oldValue = a[index]; a[index] = element; return oldValue; }
......... }
3.等等我們並沒有看到add和remove方法呀。淡定,按住ctrl點擊這個AbstractList,既然子類中沒有方法體,那一定是在父類中實現的
我們發現在父類中,這2個方法都是會拋出異常的(這些會拋出異常的方法稱為可選操作)。所以才不能使用這2個方法。但是其實想想為什麼要這樣子設計呢。為什麼不直接設計成抽象的方法呢,為什麼要拋出異常呢。
我們要知道會有很多類繼承這個AbstractList,有些方法對於有些類是沒有意義的,就比如說我們上面這個基於數組的ArrayList,既然基於數組我是必然不能改變數組的大小(數組大小固定),所以所有的會改變數組大小的方法都會拋出UnsupportedOperationException()這個異常。這些沒有意義的方法我就沒有必要重寫,如果變成抽象方法的話重寫會很繁瑣。並且事先給定了各種接口可以防止繼承類接口膨脹,因為繼承類可以隨意的創造自己的方法而不受約束,但是事先給定了可選操作,就會重寫可選操作,使容器類的使用變得輕松
public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); }
4.如果希望list可以添加刪除
可以把Arrays.asList()作為Arraylist的參數傳入就像下面這樣子
new ArrayList<>(Arrays.asList("1","2"));