结论
- Arrays.asList() 对基本数据类型支持不友好,会把基本数据类型数组仿作一个参数。
- Arrays.asList() 的参数改变后,结果得到得到List的值也会改变。
- Arrays.asList() 的结果为Arrays的一个内部类,而不是 java.util.ArrayList
测试
public class ArraysUTest {
@Test
public void asListUTest() {
int[] ints = new int[]{1, 2 , 3 , 4 , 5 , 6};
List intList = Arrays.asList(ints);
System.out.println("Arrays::asList 参数为基本数据类型数组:");
print(intList);
Integer[] integers = {1, 2, 3};
List integerList = Arrays.asList(integers);
System.out.println("Arrays::asList 参数为引用类型数组:");
print(integerList);
ints[0] = 99999;
System.out.println("改变基本类型数组后,转换的 List 结果的值:");
print(intList);
integers[0] = 9999;
System.out.println("改变引用类型数组后,转换的 List 结果的值:");
print(integerList);
System.out.println("Arrays::asList 结果的类型为:");
System.out.println(integerList.getClass());
}
private void print(List intList) {
for (Object obj : intList) {
System.out.println(obj.getClass() + "\t" + (obj.getClass().isArray() ? Array.get(obj, 0) : obj));
}
}
}
分析
先来看第二点和第三点:
Arrays.asList()实现如下:
/**
* Returns a fixed-size list backed by the specified array. (Changes to
* the returned list "write through" to the array.) This method acts
* as bridge between array-based and collection-based APIs, in
* combination with {@link Collection#toArray}. The returned list is
* serializable and implements {@link RandomAccess}.
*
* <p>This method also provides a convenient way to create a fixed-size
* list initialized to contain several elements:
* <pre>
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
* </pre>
*
* @param <T> the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
其中,ArrayList是Arrays的内部类:java.util.Arrays$ArrayList。
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
// 其他实现...
}
可以看到,这个java.util.Arrays$ArrayList直接将传入的参数数组(T... a,记为T [])保存为内部数组,使用的是同一个内存地址。所以,当数组(T[])本身改变的时候,也会同时影响到java.util.Arrays$ArrayList内部保存的数组变量。
至于第一点,则是泛型使用的限制之一:Java泛型不能使用基本类型
举个简单的例子:
List<int> list = new List<int>();// 编译前类型检查报错
泛型在编译时,会进行类型擦除,最后只保留原始类型。而原始类型只能是Object类及其子类,因此不能使用基本数据类型。
所以,Arrays.asList()并不认识基本数据类型 int,它只把 int[].class当成了一个基础类型。因此下面一段代码的结果也不难猜测:
@Test
public void testP() {
int[] ints = {1, 2, 3};
System.out.println("基本数据类型数组:");
f(ints);
Integer[] integers = {1, 2, 3};
System.out.println("封装数据类型数组:");
f(integers);
}
private <T> void f(T... p) {
for (T t : p) {
System.out.println(t);
}
}