把Java數組轉換為List時的注意事項

jopen 9年前發布 | 13K 次閱讀 Java Java開發

不幸的是并不是每件事都盡如人意。舉個例子,現在將一個Java數組轉換為List。當然,我們可以使用Arrays.toList方法,但是如果沒有慎重思考就隨便使用幾乎肯定會產生令人討厭的意外。考慮完下面這段程序并預測其輸出你就明白我的意思了:

package com.wordpress.mlangc.arrays;

import java.util.Arrays;

public class ArraysToList
{
    public static void main(final String[] args)
    {
        System.out.println(
                Arrays.asList(new String[] { "a", "b" }));

        System.out.println(
                Arrays.asList(new Integer[] { 1, 2 }));

        System.out.println(
                Arrays.asList(new int[] { 1, 2 }));

        System.out.println(
                Arrays.asList(new String[] { "a", "b" }, "c"));
    }
}

由于Javadoc對Arrays.asList的說明相當模糊,對你來說預測出程序的運行結果可能有點困難,下面我們來一步步的揭曉答案:

  • 第9行就像我們根據API所預測的那樣在我們的控制臺輸出了“[a,b]”,這正是我們樂意看到的。
  • 第12行也一樣如預期那樣輸出了“[1,2]”。
  • 第15行就不同了,當然這里不是說15與12的不同,而是一個是int另一個是Integer,因此在我們的控制臺打印出了類似這樣的結果“[[I@39172e08]”,這就不再如預期那樣了。我們得到一個包含數組中標識每個元素唯一性的地址串的list,而不是包含兩個Integer對象的list。
  • 看到上面的結果后,對于第18行輸出的類似“[[Ljava.lang.String;@20cf2c80, c]”這樣的結果就不會感到驚奇了。

但是發生了什么呢?前兩個打印語句與我們預期的結果相同,因Java語言規范規定了調用一個聲明為foo(T… t)的方法,比如foo(new T[]{bar,baz})等同于foo(bar,baz)這樣的調用。在Arrays.asList方法中T是參數類型,因此它必須為一個Object 類型,但是int不是,而int[]卻是。這就是為什么第16行的聲明等同于 Arrays.asList(new Object[] { new int[] { 1, 2 } })。

Arrays.asList(new Object[] { new int[] { 1, 2 } })

最后也是非常重要的一點,在第19行的聲明從一開始就產生了調用問題。我們告訴編譯器我們需要一個包含String數組和字符串的list,正如我們預期的那樣我們得到了我們想要的東西。

到現在為止解釋了這么多,但是我們還可以從中學到更多的東西:問題的真正來源并不是可變參數設計的很糟糕;相反的我認為這個設計很好。關于這個問題在Effective Java2第 42項規范中已經解釋地很清楚了,Arrays.asList違反了該項規范,事實上Arrays.asList作為一個反面教材,告訴了我們在使用Java的可變參數設計API時為什么要非常小心。在這里我不會再重復那篇文章里的回答,但是你自己確實需要親自去讀一下它,但是考慮到完整性我必須指出 上面有問題的聲明在使用Java1.4的編譯器下編譯的時候就會報錯,這是相當好的。現在我們仍然會使用Arrays.asList,但是為了安全要求我 們知道所面臨的問題的復雜性。下面是在將數組轉換為lists的時候我們需要遵循的規則,做到這些可以確保沒有任何意外的情況發生:

  • 如果你要將一個數組轉換為list時最好將其轉換為一個string,使用Arrays.toString代替上面的方法吧。即使對于基本類型的數組該方法也不會出現任何問題。
  • 如果你打算將一個基本類型的數組轉換為所對應的封裝類型的list,使用Apache Commons Lang吧,關于這個可能你很早就在項目中使用過了,類似下面這樣使用ArrayUtils.toObject
List<Integer> list = Arrays.asList(ArrayUtils.toObject(new int[] { 1, 2 }));
  • 如果你打算將一個引用類型的數組轉換為list,可以直接使用Arrays.asList:
List<String> list = Arrays.asList(new String[] { "a", "b" });

不要忘了告訴和你一起工作的人以確保他們不和你犯同樣的錯誤。當然,你也可以選擇僅僅記住那些使用Arrays.asList方法時可能出現問題的地方,并使用普通的for循環來代替,但是那會使你的代碼很雜亂,還會帶來性能方面的問題

原文鏈接: mlangc 翻譯: ImportNew.com - 飄揚葉
譯文鏈接: http://www.importnew.com/14996.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!