為什么Java中Arrays.asList返回值不能用add和remove方法

Arrays提供了asList()方法弊仪,可以很方便地得到一個(gè)List

List<Integer> integers = Arrays.asList(1, 2, 3, 4);

在日常操作中囱修,我們通常都會(huì)使用addremove方法對(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)ArrayListArrays的內(nèi)部類(lèi),根本不是java.util.ArrayList.

  • 假ArrayList: java.util.Arrays$ArrayList
  • 真ArrayList: java.util.ArrayList

Arrays.asList

Arrays.asList(T... a)中返回的ArrayListArrays的內(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)例子代碼)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末等龙,一起剝皮案震驚了整個(gè)濱河市处渣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蛛砰,老刑警劉巖罐栈,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泥畅,居然都是意外死亡荠诬,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)位仁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)柑贞,“玉大人,你說(shuō)我怎么就攤上這事聂抢【唬” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵琳疏,是天一觀的道長(zhǎng)有决。 經(jīng)常有香客問(wèn)我闸拿,道長(zhǎng),這世上最難降的妖魔是什么书幕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任新荤,我火速辦了婚禮,結(jié)果婚禮上按咒,老公的妹妹穿的比我還像新娘迟隅。我一直安慰自己,他們只是感情好励七,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布智袭。 她就那樣靜靜地躺著,像睡著了一般掠抬。 火紅的嫁衣襯著肌膚如雪吼野。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天两波,我揣著相機(jī)與錄音瞳步,去河邊找鬼。 笑死腰奋,一個(gè)胖子當(dāng)著我的面吹牛单起,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播劣坊,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嘀倒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了局冰?” 一聲冷哼從身側(cè)響起测蘑,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎康二,沒(méi)想到半個(gè)月后碳胳,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沫勿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年挨约,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片产雹。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烫罩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出洽故,到底是詐尸還是另有隱情,我是刑警寧澤盗誊,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布时甚,位于F島的核電站隘弊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏荒适。R本人自食惡果不足惜梨熙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刀诬。 院中可真熱鬧咽扇,春花似錦、人聲如沸陕壹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)糠馆。三九已至嘶伟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間又碌,已是汗流浹背九昧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毕匀,地道東北人铸鹰。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像皂岔,于是被迫代替她去往敵國(guó)和親蹋笼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容