前言
最近在項目上線的時候發現一個問題,從后台報錯日志看: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中的坑就說到這里,有補充的歡迎留言。