最近,抽空把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 class="brush:php;toolbar:false"> * List<String> stooges = Arrays.asList("Larry", "Moe", "Curly"); ** * @param a the array by which the list will be backed * @return a list view of the specified array */ @SafeVarargs public static
問題發現
根據上述方法的描述,我們先來寫幾個例子:
/** * @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; } }
其原始程式碼如下:
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(); } }
其原始程式碼如下:
/** * @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)
其原始程式碼如下:
/** * @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); } }
其原始程式碼如下:
/** * @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); } }
其原始程式碼如下:
rrreee其原始程式碼如下:
rrreee
從這個內部類別ArrayList的實作可以看出,它繼承了抽象類別.util.AbstractListrrreee
正是因為java.util.Arrays類別的內部類別ArrayList沒有重寫add和remove方法,所以,當我們呼叫其實add方法時,其實就是呼叫了AbstractList類別的add方法,結果就是直接拋出UnsupportedOperationException異常。
同理,在呼叫remove方法,或呼叫與add、remove方法相關聯的其它方法(如addAll)同樣會遇到UnsupportedOperationException異常。
addAll的例子:
rrreeerrreee
set的例子:
rrreee再拋出UnsupportedOperationException異常。
結果如下:
[Welcome, to, Java, world]
[Welcome, to, hello, world] 使用場景
從上述的例子和簡單類分析來看,ArraysList , 使用此方法可以將一個變長參數或陣列轉換成List 。
但是,產生的List的長度是固定的;能夠進行修改操作(例如,修改某個位置的元素);不能執行影響長度的操作(如add、remove等操作)。會拋出UnsupportedOperationException異常。
Arrays.asList比較適合那些已經有數組資料或一些元素,而需要快速建立一個List,只用於讀取操作,而不進行新增或刪除操作的場景。
🎜如果,想要根據已知數組數據,快速取得一個可進行增刪改查的列表List,一個比較簡單的方法如下:🎜🎜重新使用java.util.ArrayList包裝一層。 🎜rrreee🎜 🎜🎜🎜🎜結果如下:🎜🎜[Welcome, to, Java, world]🎜[Welcome, to謝謝 Java, world, Cool~~~]🎜🎜本站的支持! 🎜🎜更多java 源碼分析Arrays.asList方法詳解相關文章請關注PHP中文網! 🎜