讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議65:避開基本類型數組轉換列表陷阱 >

建議65:避開基本類型數組轉換列表陷阱

我們在開發過程中經常會使用Arrays和Collections這兩個工具類在數組和列表之間轉換,非常方便,但也有時候會出現一些奇怪的問題,來看如下代碼:


public static void main(Stringargs){

intdata={1,2,3,4,5};

List list=Arrays.asList(data);

System.out.println("列表中的元素數量是:"+list.size());

}


也許你會說,這很簡單,list變量的元素數量當然是5了。但是運行後打印出來的列表數量卻是1。

事實上data確實是一個有5個元素的int類型數組,只是通過asList轉換成列表後就只有1個元素了,這是為什麼呢?其他4個元素到什麼地方去了呢?

我們仔細看一下Arrays.asList的方法說明:輸入一個變長參數,返回一個固定長度的列表。注意這裡是一個變長參數,看源代碼:


public static<T>List<T>asList(T……a){

return new ArrayList<T>(a);

}


asList方法輸入的是一個泛型變長參數,我們知道基本類型是不能泛型化的,也就是說8個基本類型不能作為泛型參數,要想作為泛型參數就必須使用其所對應的包裝類型。那前面的例子傳遞了一個int類型的數組,為什麼程序沒有報編譯錯呢?

在Java中,數組是一個對象,它是可以泛型化的,也就是說我們的例子是把一個int類型的數組作為了T的類型,所以轉換後在List中就只有一個類型為int數組的元素了,我們打印出來看看,代碼如下:


public static void main(String args){

intdata={1,2,3,4,5};

List list=Arrays.asList(data);

System.out.println("元素類型:"+list.get(0).getClass());

System.out.println("前後是否相等:"+data.equals(list.get(0)));

}


輸出的結果是:


元素類型:class [I

前後是否相等:true


很明顯,放在列表中的元素是一個int數組,可能有讀者要問了,為什麼「元素類型:」後的class是"[I"?我們並沒有指明是數組(Array)類型呀!這是因為JVM不可能輸出Array類型,因為Array是屬於java.lang.reflect包的,它是通過反射訪問數組元素的工具類。在Java中任何一個數組的類都是"[I",究其原因就是Java並沒有定義數組這一個類,它是在編譯器編譯的時候生成的,是一個特殊的類,在JDK的幫助中也沒有任何數組類的信息。

弄清楚了問題,修改方案也就誕生了,直接使用包裝類即可,代碼如下:


public static void main(String args){

Integerdata={1,2,3,4,5};

List list=Arrays.asList(data);

System.out.println("列表中的元素數量是:"+list.size());

}


僅僅修改了加粗字體部分,把int替換為Integer即可讓輸出元素數量為5。需要說明的是,不僅僅是int類型的數組有這個問題,其他7個基本類型的數組也存在相似的問題,這就需要讀者注意了,在把基本類型數組轉換成列表時,要特別小心asList方法的陷阱,避免出現程序邏輯混亂的情況。

注意 原始類型數組不能作為asList的輸入參數,否則會引起程序邏輯混亂。