1. 程式人生 > >Arrays.asList中所遇到的坑

Arrays.asList中所遇到的坑

前言

最近在專案上線的時候發現一個問題,從後臺報錯日誌看:java.lang.UnsupportedOperationException異常
從程式碼定位來看,原來是使用了Arrays.asList()方法時把一個數組轉化成List列表時,對得到的List列表進行add()和remove()操作, 所以導致了這個問題。

對於這個問題,現在來總結下,當然會總結Arrays下面的一些坑。

原始碼分析

首先,遇到問題不可怕,遇到問題解決就是了,但是必須要保證下次不會再犯相同的問題。
Arrays.asList返回的是同樣的ArrayList,為什麼就不能使用add和remove方法呢?

1,檢視Arrays.asList 原始碼
,

2,檢視此ArrayList結構:

3, 在檢視AbstractList結構:

果然,UnsupportedOperationException 是這裡丟擲的,因為Arrays中的ArrayList並沒有實現此方法,故丟擲了異常。
所以說 Arrays.asList 返回的 List 是一個不可變長度的列表,此列表不再具備原 List 的很多特性,因此慎用 Arrays.asList 方法。

Arrays中其他坑

1,下面程式輸出是什麼?

列印結果是:1
由上面asList 原始碼我們可以看到返回的 Arrays 的內部類 ArrayList 構造方法接收的是一個型別為 T 的陣列,而基本型別是不能作為泛型引數的,所以這裡引數 a 只能接收引用型別,自然為了編譯通過編譯器就把上面的 int[] 陣列當做了一個引用引數,所以 size 為 1,要想修改這個問題很簡單,將 int[] 換成 Integer[] 即可。所以原始型別不能作為 Arrays.asList 方法的引數,否則會被當做一個引數。

2,Collections.toArray報錯問題
大家可以看下 java.util.ArrayList 原始碼 中特別標記有一句話如下:

Bug地址:https://bugs.java.com/view_bug.do?bug_id=6260652
那下面來試驗下什麼情況下會出現這種異常:

如上圖,這種控制檯列印的結果如下:
class [Ljava.lang.String;
Exception in thread "main" java.lang.ArrayStoreException: java.lang.Object

我們檢視Arrays中ArrayList的toArray原始碼:


因為asList返回的是一個String陣列,所以這裡toArray返回的其實是String[]型別,只不過是這裡做了一個向上轉型,將String[]型別轉為Object[]型別罷了。
但是注意,雖然返回的引用為Object[],但實際的型別還是String[],當你往一個引用型別和實際型別不匹配的物件中新增元素時,就是報錯。
具體大家可以參考Java向上轉型和向下轉型的相關知識點。

關於Arrays中的坑就說到這裡,有補充的歡迎留言。