import java.io.PrintStream;
import java.util.Arrays;
import org.junit.Test;
public class ArraysAsList {
public static void main(String[] args) {
/**
* 最近在用 Arrays 的 asList() 生成的 List 時,List 元素的個數時而不正確。
* 經多次測試,只要傳遞的基本類型的數組,生成 List 的元素個數均爲1 傳遞對象數組,元素個數正確
*/
char[] arrChar = { 'a', 'b' };
Arrays.asList(arrChar).size(); // 結果爲1;
int[] arrInt = { 1, 2, 4 };
Arrays.asList(arrInt).size(); // 結果爲1;
String[] arrString = { "A", "B", "C" };
Arrays.asList(arrString).size(); // 結果爲3;
}
/**
* 跟源碼:
* public static <T> List<T> asList(T... a) {
* return new ArrayList<T>(a);
* }
*
* 繼續跟,Arrays的私有內部類ArrayList (沒搞明白,爲什麼這裏也起名爲 ArrayList)
*
* private final E[] a;
*
* ArrayList(E[] array) {
* if (array==null)
* throw new NullPointerException();
* a = array;
* }
*
* public int size() {
* return a.length;
* }
*/
}
/**
* 發現問題出在java5 的可變參數上。於是寫了demo,測試。
*/
class TestArray {
PrintStream out = System.out;
@Test
public void array() {
char[] arrc = { 'a', 'b', 'c', 'd', 'e' };
out.println("傳遞char數組:");
print(arrc);
out.println("直接傳遞:");
print('a', 'b', 'c', 'd', 'e');
out.println("----------------------------");
int[] arri = { 1, 2, 3, 4, 5 };
out.println("傳遞int數組:");
print(arri);
out.println("直接傳遞:");
print(1, 2, 3, 4, 5);
out.println("----------------------------");
Integer[] arrInt = { 1, 2, 3, 4, 5};
out.println("傳遞Integer數組:");
/**[Notice]
* The argument of type Integer[] should explicitly
* be cast to Object[] for the invocation of the
* varargs method print(Object...) from type TestArray.
* It could alternatively be cast to Object for
* a varargs invocation
*/
print((Object)arrInt);
out.println("直接傳遞:");
print(1, 2, 3, 4, 5);
out.println("----------------------------");
String[] arrs = { "a", "b", "c", "d", "e" };
out.println("傳遞String數組:");
/**[Notice]
* The argument of type String[] should explicitly
* be cast to Object[] for the invocation of the
* varargs method print(Object...) from type TestArray.
* It could alternatively be cast to Object for
* a varargs invocation
*/
print((Object)arrs);
out.println("直接傳遞:");
print('a', 'b', 'c', 'd', 'e');
out.println("----------------------------");
}
public void print(Object... arr) {
out.print("內容:" + Arrays.toString(arr));
out.println("\t\t數組長度:" + arr.length + " ");
}
}
/******************************************************************
傳遞char數組:
內容:[[C@4b1e0ac] 數組長度:1
直接傳遞:
內容:[a, b, c, d, e] 數組長度:5
----------------------------
傳遞int數組:
內容:[[I@3a153e9c] 數組長度:1
直接傳遞:
內容:[1, 2, 3, 4, 5] 數組長度:5
----------------------------
傳遞Integer數組:
內容:[1, 2, 3, 4, 5] 數組長度:5
直接傳遞:
內容:[1, 2, 3, 4, 5] 數組長度:5
----------------------------
傳遞String數組:
內容:[a, b, c, d, e] 數組長度:5
直接傳遞:
內容:[a, b, c, d, e] 數組長度:5
----------------------------
******************************************************************/
/**
* java 5 可變參數,直接傳遞值與傳遞數組處理的機制不太相同。如果直接傳遞
* 數組,基本類型數組將被視爲一個對象而不會被解析成數組,如果直接傳遞參數
* 將能正常解析。因此傳遞基本類型數組時強烈建議轉爲其封裝類對象的數組
* int ->Integer ,long->Long …………。(未對其封裝)
*/
/** 這樣寫就很清楚了吧
package cn.sunzn.array;
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
int[] intArray = {1,2,3};
List<int[]> myList = Arrays.asList(intArray);
System.out.println(myList.size());
System.out.println(myList.get(0).length);
}
}
*/
/******************************************************************
* 輸出結果爲:1 3
******************************************************************/
/******************************************************************
* 所以定義就不難理解了
* public static <T> List<T> asList(T... a) {
* return new ArrayList<T>(a);
* }
* 這個 T 必須是對象類型。好比我們不能 new ArrayList<int> 只能 new ArrayList<Integer>
******************************************************************/
==========================================================
jdk 1.4對java.util.Arrays.asList的定義,函數參數是Object[]。所以,在1.4中asList()並不支持基本類型的數組作參數。
jdk 1.5中,java.util.Arrays.asList的定義,函數參數是Varargs, 採用了泛型實現。同時由於autoboxing的支持,使得可以支持對象數組以及基本類型數組。
但在使用過程中發現jdk1.5中存在一個BUG。就是等參數爲基本類型的數組時,函數的行爲發生了變異:它不是把這個數組轉換爲List,而是把這個數組整體作爲返回List中的第一個元素,要取得轉換後的結果,得首先get(0)才行。
到網上google了一下,Sun好像認爲這並不是個問題。理由如下:
Arrays.asList is now a vararg method, and the behavior is as intended: asList(int[] ...)
The Java generics implementation does not support non-reference type parameters.
This is all standard Java 5.0 stuff.
URL:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6353471
雖然如此,但因此函數的行爲就可能產生了歧義,對調用者還是會產生誤導的,我認爲這終歸還應該是個問題的,如能解決是最好的了。