问题1:
@Test
public void Test1(){
int[] arr1 = {1,2,3};
Integer[] arr2 = {1,2,3};
List<int[]> ints = Arrays.asList(arr1); //泛型问int数组
List<Integer> integers = Arrays.asList(arr2); //泛型是Integer
System.out.println(ints);
//[[I@80169cf] 输出的是数组的地址值,证明它是list里面套的数组
System.out.println(integers);
//[1, 2, 3] 输出的是数组的每个值,证明它是把Integer数组转换成了泛型为Integer的集合
}
原因:只能是把 int 装箱为 Integer,不可能把 int 数组装箱为 Integer 数组。我们知道,Arrays.asList 方法传入的是一个泛型 T 类型可变参数,最终 int 数组整体作为了一个对象成为了泛型类型 T
解决1:
1.使用Integer数组不使用int数组(上面一句演示Integer数组了,这里不再演示)
2.使用jdk1.8以后方式解决,使用 Arrays.stream 方法来转换,如下代码:
@Test
public void Test0(){
int[] arr1 = {1,2,3};
//使用jdk8的新特性进行转换
List ints = Arrays.stream(arr1).boxed().collect(Collectors.toList());
System.out.println(ints); //[1, 2, 3]
System.out.println(ints.size()); //3
System.out.println(ints.get(0).getClass()); //class java.lang.Integer
}
可以看到第一个坑是,不能直接使用 Arrays.asList 来转换基本类型数组。
问题2:
转换后的list能否正常使用
@Test
public void Test2(){
Integer[] arr2 = {1,2,3};
List<Integer> integers = Arrays.asList(arr2); //泛型是Integer
integers.add(1); //java.lang.UnsupportedOperationException
}
兴许到这你会说,我都已经把数组转换成list了,为什么不能添加元素呢?点进Arrays.asList源码
我们会发现,使用Arrays.asList将数组转换成ArrayList所new的并不是我们平常的ArrayList类,而是Arrays类中的一个静态内部类,而且该内部类虽然是ArrayList但是它不支持增删操作,因为它没有重写父类中的add等方法,所以在调用add方法的时候会去找父类的add,父类的add就会抛异常。
问题3:
@Test
public void Test3(){
Integer[] arr2 = {1,2,3};
List<Integer> integers = Arrays.asList(arr2); //泛型是Integer
arr2[0] = 6; //修改数组
integers.set(1,8); //修改集合
System.out.println(Arrays.toString(arr2)); //[6, 8, 3]
System.out.println(integers); //[6, 8, 3]
/*
原始数组:[1,2,3]
修改后数组:[6, 8, 3]
修改后集合:[6, 8, 3]
*/
}
我们可以发现,修改数组或集合,都会对二者产生影响,这并不是我们想要的,产生这种bug的原因是什么呢?
看一下 ArrayList 的实现,可以发现 ArrayList 其实是直接使用了原始的数组,新的 List 持有了原始数据的引用,可能会导致原始数据也无法 GC 的问题,最终导致 OOM。
解决2和3:
问题2:数组使用Arrays.asList转换成list集合后不能使用其增删等方法,而且长度不可改变。
问题3:相互修改产生Bug;
解决思路很简单,我们在new一个List集合即可,把转换的集合数据传进去。
@Test
public void Test4(){
Integer[] arr2 = {1,2,3};
List<Integer> integers = Arrays.asList(arr2); //泛型是Integer
ArrayList<Integer> list = new ArrayList<>(integers); //传入上一个集合的元素
arr2[0] = 6; //修改数组
integers.set(1,8); //修改集合
list.set(2,9); //修改新集合
System.out.println(Arrays.toString(arr2)); //[6, 8, 3]
System.out.println(integers); //[6, 8, 3]
System.out.println(list); //[1, 2, 9]
/*
我们新new的list没有受到数组和使用Arrays.asList转换的集合修改的影响,
因为这个list是我们新new的,它们不在同一个内存空间中,相互不影响
*/
list.add(5);
System.out.println(list); //[1, 2, 9, 5]
}
可以看到我们新的list是没有问题的。