Arrays.asList类型转换结果的坑
文章目录
在各种Java编程规范中都强调尽量不用java.util.Arrays.asList()方法以避免调用此方法生成的List无法进行修改操作,个人近期在使用过程中发现该方法的另外一个坑,简单记录下。
问题描述
在程序中需要检测某个元素是否在数组中,处于缩短代码篇幅的考虑,自己采用了Arrays.asList方法将其转化为List然后调用contains方法来判断:
public static boolean checkContains(int ele) {
int[] data = {11, 12, 13, 14};
return Arrays.asList(data).contains(ele);
}
但实际执行结果和自己预期的不一致,理论上的结果应该为true,而实际返回的结果为false

问题分析
在Debug模式下查看Arrays.asList(data)返回的值,发现其返回的结果不是预期中的List<Integer>而是List<int[]>,从而导致调用List.contains()方法失效!

在IDEA中将Arrays.asList(data)返回的结果单独赋值给一个变量,可发现其类型确实为List<int[]>,若将结果类型修改为List<Integer>则会报错,如下图所示:

在上图右边的报错信息中有如下说明信息:
no instance(s) of type variable(s) exist so that int[] conforms to Integer inference variable T has incompatible bounds: equality constraints: Integer lower bounds: int[]
上述文字的核心内容为Arrays.asList需要获取Object类型,而int是原生类型,但int[]符合要求,因此Arrays.asList()方法会将原始的int数组视作一个int[]对象进行处理,从而导致此结果1。
解决方案
找到问题原因后修改起来也很容易,按照通常的编程习惯,只需要把数组的定义从int修改为Integer即可
public static boolean checkContains(int ele) {
Integer[] data = {11, 12, 13, 14};
List<Integer> dataList = Arrays.asList(data);
return dataList.contains(ele);
}
执行结果符合预期

Update:
在Stackoverflow上找到一个类似问题2,在其回答中提供了一些其它实现方案:
-
JDK8实现int[] ints = new int[] {1,2,3,4,5}; List<Integer> list11 =Arrays.stream(ints).boxed().collect(Collectors.toList()); -
JDK16实现int[] ints = new int[] {1,2,3,4,5}; Arrays.stream(ints).boxed().toList();
asList不可变原因分析
查看Arrays.asList返回结果中的List,发现其返回的是内部自己实现的ArrayList,但该ArrayList没有重写add方法。

但AbstractList默认没有实现add()方法而是抛出一个异常,从而导致无法通过调用add()方法添加元素。
