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
虽然如此,但因此函数的行为就可能产生了歧义,对调用者还是会产生误导的,我认为这终归还应该是个问题的,如能解决是最好的了。