Arrays
提供了asList()
方法弊仪,可以很方便地得到一個(gè)List
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
在日常操作中囱修,我們通常都會(huì)使用add
和remove
方法對(duì)List
的元素進(jìn)行管理。如
integers.add(5);
integers.remove(1)
這時(shí)就出現(xiàn)了異常:java.lang.UnsupportedOperationException
探究
Arrays.asList()
源碼注釋如下挣柬,指出返回了一個(gè)定長(zhǎng)的list
, 這個(gè)方法充當(dāng)array
系列API和collection
系列API之間的橋梁钥顽。所以說(shuō),返回值舞箍,只是數(shù)組簡(jiǎn)單包裝而成的List
而已舰褪,并不能改變其長(zhǎng)度。
/**
* 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 <T> the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
Think In Java 中做了詳細(xì)的解釋?zhuān)?/p>
It’s also possible to use the output of Arrays.asList( ) directly, as a List, but the underlying representation in this case is the array, which cannot be resized. If you try to add( ) or delete( ) elements in such a list, that would attempt to change the size of an array, so you’ll get an "Unsupported Operation" error at run time.
不過(guò)沒(méi)有關(guān)系疏橄,我們可以用ArrayList
的構(gòu)造方法占拍,來(lái)創(chuàng)建一個(gè)新的ArrayList
略就,然后再進(jìn)行增刪操作。
Integer[] ints = {1, 2, 3, 4};
ArrayList<Integer> integers = new ArrayList<>(Arrays.asList(ints));
integers.add(5);
這樣就OK啦~
且慢晃酒!Arrays.asList()
源碼里返回的不就是ArrayList
本身嗎表牢,怎么會(huì)不能add
, remove
呢?
點(diǎn)擊跳轉(zhuǎn)到這個(gè)ArrayList
的定義, 發(fā)現(xiàn)原來(lái)ArrayList
是Arrays
的內(nèi)部類(lèi),根本不是java.util.ArrayList
.
- 假ArrayList:
java.util.Arrays$ArrayList
- 真ArrayList:
java.util.ArrayList
Arrays.asList
Arrays.asList(T... a)
中返回的ArrayList
是Arrays
的內(nèi)部類(lèi)贝次,繼承了AbstractList
崔兴。所以說(shuō)調(diào)用add
方法的時(shí)候,其實(shí)調(diào)用了父類(lèi)AbstractList
的方法蛔翅,方法源碼如下:
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
直接拋出了異常敲茄,跟我們之前實(shí)踐的情況一致。
ArrayList
我們通常用的ArrayList
山析,繼承了AbstractList
堰燎,并重寫(xiě)了add
, remove
等方法,源碼如下:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public E remove(int index) {
rangeCheck(index)
modCount++;
E oldValue = elementData(index)
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its wor
return oldValue;
}
Arrays.asList()的其他局限性
沒(méi)錯(cuò)笋轨,還有坑秆剪。
asList()
的返回值List<?>
會(huì)指定一個(gè)認(rèn)為最合適元素類(lèi)型,這點(diǎn)會(huì)造成一定的困惑翩腐。如:Arrays.asList(1, 2, 3, 4)
得到的就是一個(gè)List<Integer>
. Think In Java 中的例子如下:
//: holding/AsListInference.java
// Arrays.asList() makes its best guess about type.
import java.util.*;
class Snow {}
class Powder extends Snow {}
class Light extends Powder {}
class Heavy extends Powder {}
class Crusty extends Snow {}
class Slush extends Snow {}
public class AsListInference {
public static void main(String[] args) {
List<Snow> snow1 = Arrays.asList(new Crusty(), new Slush(), new Powder());
// Won’t compile:
// List<Snow> snow2 = Arrays.asList(new Light(), new Heavy());
// Compiler says:
// found : java.util.List<Powder>
// required: java.util.List<Snow>
// Collections.addAll() doesn’t get confused:
List<Snow> snow3 = new ArrayList<Snow>();
Collections.addAll(snow3, new Light(), new Heavy());
// Give a hint using an explicit type argument specification:
List<Snow> snow4 = Arrays.<Snow>asList(new Light(), new Heavy());
}
} ///:~
Arrays.asList(new Light(), new Heavy())
返回值為List<Power>
, 把它賦值給類(lèi)型為List<Snow>
的snow2
就會(huì)報(bào)錯(cuò)鸟款。
遇到這種情況,解決方法是茂卦,用Collection.addAll()
替代何什,或者手動(dòng)指定類(lèi)型(見(jiàn)例子代碼)。