java 源碼分析Arrays.asList方法詳解_java

來源:互聯網
上載者:User

最近,抽空把java Arrays 工具類的asList 方法做了源碼分析,在網上整理了相關資料,記錄下來,希望也能協助讀者!

Arrays工具類提供了一個方法asList, 使用該方法可以將一個變長參數或者數群組轉換成List 。

其原始碼如下:

 /**  * Returns a fixed-size list backed by the specified array. (Changes to  * the returned list "write through" to the array.) This method acts  * as bridge between array-based and collection-based APIs, in  * combination with {@link Collection#toArray}. The returned list is  * serializable and implements {@link RandomAccess}.  *  * <p>This method also provides a convenient way to create a fixed-size  * list initialized to contain several elements:  * <pre>  *  List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");  * </pre>  *  * @param a the array by which the list will be backed  * @return a list view of the specified array  */ @SafeVarargs public static <T> List<T> asList(T... a) {  return new ArrayList<>(a); } 

問題發現

根據上述方法的描述,我們先來編寫幾個例子:

/** * @author wangmengjun * */public class ArrayExample {  public static void main(String[] args) {    /**使用變長參數*/  List<String> array1 = Arrays.asList("Welcome", "to","Java", "world");  System.out.println(array1);    /**使用數組*/  List<String> array2 = Arrays.asList(new String[] {"Welcome", "to","Java", "world"});  System.out.println(array2); }}

 運行上述程式,輸出如下內容。

[Welcome, to, Java, world]
[Welcome, to, Java, world]

心血來潮,突然想在建立的列表中添加一個字串“Cool~~~”,  走一個。

 /**使用變長參數*/  List<String> array1 = Arrays.asList("Welcome", "to","Java", "world");  array1.add("Cool~~~");

結果,遇到一個UnsupportedOperationException異常:

Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(Unknown Source) at java.util.AbstractList.add(Unknown Source) at test.ArrayExample.main(ArrayExample.java:36)

不可思議,new ArrayList<>(a)產生的列表調用add方法,竟然遇到問題。

原因尋找

那麼問題來了,到底發生了什麼事情?帶著疑問,去查看一下Arrays.asList中使用的ArrayList到底長啥樣?

原來Arrays的asList方法使用的ArrayList類是一個內部定義的類,而不是java.util.ArrayList類。

其原始碼如下:

 /**   * @serial include   */  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 int size() {      return a.length;    }    public Object[] toArray() {      return a.clone();    }    public <T> T[] toArray(T[] a) {      int size = size();      if (a.length < size)        return Arrays.copyOf(this.a, size,                   (Class<? extends T[]>) a.getClass());      System.arraycopy(this.a, 0, a, 0, size);      if (a.length > size)        a[size] = null;      return a;    }    public E get(int index) {      return a[index];    }    public E set(int index, E element) {      E oldValue = a[index];      a[index] = element;      return oldValue;    }    public int indexOf(Object o) {      if (o==null) {        for (int i=0; i<a.length; i++)          if (a[i]==null)            return i;      } else {        for (int i=0; i<a.length; i++)          if (o.equals(a[i]))            return i;      }      return -1;    }    public boolean contains(Object o) {      return indexOf(o) != -1;    }  }

從這個內部類ArrayList的實現可以看出,它繼承了抽象類別java.util.AbstractList<E>, 但是沒有重寫add和remove方法,沒有給出具體的實現。

但是,預設情況下,java.util.AbstractList類在add、set以及remove方法中,直接會拋出UnsupportedOperationException異常。AbstractList的部分原始碼如下:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {  /**   * Sole constructor. (For invocation by subclass constructors, typically   * implicit.)   */  protected AbstractList() {  }  public E set(int index, E element) {    throw new UnsupportedOperationException();  }  /**   * {@inheritDoc}   *   * <p>This implementation always throws an   * {@code UnsupportedOperationException}.   *   * @throws UnsupportedOperationException {@inheritDoc}   * @throws ClassCastException      {@inheritDoc}   * @throws NullPointerException     {@inheritDoc}   * @throws IllegalArgumentException   {@inheritDoc}   * @throws IndexOutOfBoundsException   {@inheritDoc}   */  public void add(int index, E element) {    throw new UnsupportedOperationException();  }  /**   * {@inheritDoc}   *   * <p>This implementation always throws an   * {@code UnsupportedOperationException}.   *   * @throws UnsupportedOperationException {@inheritDoc}   * @throws IndexOutOfBoundsException   {@inheritDoc}   */  public E remove(int index) {    throw new UnsupportedOperationException();  }}

 正是因為java.util.Arrays類的內部類ArrayList沒有重寫add和remove方法,所以,當我們調用其add方法時,其實就是調用了AbstractList類的add方法,結果就是直接拋出UnsupportedOperationException異常。

同理,在調用remove方法,或者調用與add、remove方法相關聯的其它方法(如addAll)同樣會遇到UnsupportedOperationException異常。

addAll的例子:

/** * @author wangmengjun * */public class ArrayExample {  public static void main(String[] args) {    /**使用變長參數*/    List<String> array1 = Arrays.asList("Welcome", "to", "Java", "world");    array1.addAll(Arrays.asList("AAA", "BBB"));  }}
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(Unknown Source) at java.util.AbstractList.add(Unknown Source) at java.util.AbstractCollection.addAll(Unknown Source) at test.ArrayExample.main(ArrayExample.java:36) 

set的例子:

/** * @author wangmengjun * */public class ArrayExample {  public static void main(String[] args) {    /**使用變長參數*/    List<String> array1 = Arrays.asList("Welcome", "to", "Java", "world");    System.out.println(array1);        //將Java替換成hello    array1.set(2, "hello");    System.out.println(array1);  }}

正是由於Arrays的內部類ArrayList重寫了set方法,所以上述程式能夠正常運行,不會再拋出UnsupportedOperationException異常。

結果如下:

[Welcome, to, Java, world]
[Welcome, to, hello, world] 

使用情境

從上述的例子和簡單分析來看,Arrays工具類提供了一個方法asList, 使用該方法可以將一個變長參數或者數群組轉換成List 。

但是,產生的List的長度是固定的;能夠進行修改操作(比如,修改某個位置的元素);不能執行影響長度的操作(如add、remove等操作)。會拋出UnsupportedOperationException異常。

Arrays.asList比較適合那些已經有數組資料或者一些元素,而需要快速構建一個List,只用於讀取操作,而不進行添加或刪除操作的情境。

如果,想要根據已知數組資料,快速擷取一個可進行增刪改查的列表List,一個比較簡單的方法如下:

重新使用java.util.ArrayList封裝一層。

/** * @author wangmengjun * */public class ArrayExample {  public static void main(String[] args) {    /**使用變長參數*/    List<String> array1 = new ArrayList<>(Arrays.asList("Welcome", "to", "Java", "world"));    System.out.println(array1);    array1.add("Cool~~~");    System.out.println(array1);  }}

結果如下:

[Welcome, to, Java, world]
[Welcome, to, Java, world, Cool~~~]

感謝閱讀,希望能協助到大家,謝謝大家對本站的支援!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.