不幸的是并不是每件事都盡如人意。舉個例子,現在将一個Java數組轉換為List。當然,我們可以使用Arrays.toList方法,但是如果沒有慎重思考就随便使用幾乎肯定會産生令人讨厭的意外。考慮完下面這段程式并預測其輸出你就明白我的意思了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
由于Javadoc對Arrays.asList的說明相當模糊,對你來說預測出程式的運作結果可能有點困難,下面我們來一步步的揭曉答案:
· 第9行就像我們根據API所預測的那樣在我們的控制台輸出了“[a,b]”,這正是我們樂意看到的。
· 第12行也一樣如預期那樣輸出了“[1,2]”。
· 第15行就不同了,當然這裡不是說15與12的不同,而是一個是int另一個是Integer,是以在我們的控制台列印出了類似這樣的結果“[[[email protected]]”,這就不再如預期那樣了。我們得到一個包含數組中辨別每個元素唯一性的位址串的list,而不是包含兩個Integer對象的list。
· 看到上面的結果後,對于第18行輸出的類似“[[Ljava.lang.String;@20cf2c80, c]”這樣的結果就不會感到驚奇了。
但是發生了什麼呢?前兩個列印語句與我們預期的結果相同,因Java語言規範規定了調用一個聲明為foo(T… t)的方法,比如foo(newT[]{bar,baz})等同于foo(bar,baz)這樣的調用。在Arrays.asList方法中T是參數類型,是以它必須為一個Object 類型,但是int不是,而int[]卻是。這就是為什麼第16行的聲明等同于 Arrays.asList(new Object[] { newint[] { 1, 2 } })。
1 | |
最後也是非常重要的一點,在第19行的聲明從一開始就産生了調用問題。我們告訴編譯器我們需要一個包含String數組和字元串的list,正如我們預期的那樣我們得到了我們想要的東西。
到現在為止解釋了這麼多,但是我們還可以從中學到更多的東西:問題的真正來源并不是可變參數設計的很糟糕;相反的我認為這個設計很好。關于這個問題在EffectiveJava2第 42項規範中已經解釋地很清楚了,Arrays.asList違反了該項規範,事實上Arrays.asList作為一個反面教材,告訴了我們在使用Java的可變參數設計API時為什麼要非常小心。在這裡我不會再重複那篇文章裡的回答,但是你自己确實需要親自去讀一下它,但是考慮到完整性我必須指出上面有問題的聲明在使用Java1.4的編譯器下編譯的時候就會報錯,這是相當好的。現在我們仍然會使用Arrays.asList,但是為了安全要求我 們知道所面臨的問題的複雜性。下面是在将數組轉換為lists的時候我們需要遵循的規則,做到這些可以確定沒有任何意外的情況發生:
· 如果你要将一個數組轉換為list時最好将其轉換為一個string,使用Arrays.toString代替上面的方法吧。即使對于基本類型的數組該方法也不會出現任何問題。
· 如果你打算将一個基本類型的數組轉換為所對應的封裝類型的list,使用ApacheCommons Lang吧,關于這個可能你很早就在項目中使用過了,類似下面這樣使用ArrayUtils.toObject:
1 | |
請注意:一般情況下推薦使用原始資料類型數組而不是裝箱後的原始資料類型清單。
· 如果你打算将一個引用類型的數組轉換為list,可以直接使用Arrays.asList:
1 | |
不要忘了告訴和你一起工作的人以確定他們不和你犯同樣的錯誤。當然,你也可以選擇僅僅記住那些使用Arrays.asList方法時可能出現問題的地方,并使用普通的for循環來代替,但是那會使你的代碼很雜亂,還會帶來性能方面的問題。
原文連結: mlangc 翻譯: ImportNew.com - 飄揚葉
譯文連結: http://www.importnew.com/14996.html