问题出现的背景
本周在使用Arrays.asList方法时,由于对该方法不够了解,导致在使用过程中产生空指针问题。下面的代码示例展现了简化出现问题的原因,该段代码想要判断当前的登陆者是否为代理人。首先是我会从中券模板中获取该券模板中的代理人,代理人存储的格式为”zhaosan,wangsi”;接下来我通过一系列的工具类将该数据转化为数组,最后和当前登陆者去做对比。
public static void whatIsProblem() {
String agentId = null;
String loginId = "gy";
String[] agentIds = StringUtils.split(agentId, ",");
List<String> list = Arrays.asList(agentIds);
boolean isSuccess = list.contains(loginId);
}
在第5行代码调用Arrays.asList时,如果数组为null,会出现空指针的问题,进而会导致用户无法访问该页面。
问题出现的原因
第一层:开发阶段
在代码实现过程中,有考虑过这块的实现会有问题,但是由于事情比较多,没有仔细推敲,就把这块给忽略了。这里也印证了一点,可能出现问题的地方一定会出现问题,在写代码的过程中,一定要熟悉自己使用的工具类和工具方法,不熟悉的不要使用。
第二层:功能自测
在功能自测时,没有考虑这种场景,在写测试用例时,也没有覆盖到该场景,导致在预发时才暴露出来这个空指针的问题。其实该问题是主流程中的一个业务场景,在自测时稍加注意,就不会出现该问题。
Arrays.asList源代码分析
首先来看下Arrays.asList的实现,初始化一个ArrayList对象,此处的ArrayList是Arrays的静态类,并非我们经常使用的集合类。
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
asList方法是数组转换为集合的媒介,方法中传入几个元素,就会初始化相应大小的集合,ArrayList的构造对象在初始化集合元素时,会判断数组元素是否为null,如果为null,会抛出空指针异常。
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);//如果为null,会抛出空指针异常
}
}
另外一个不会有问题的case
public static void whatIsProblem2() {
String agentId = "";
String[] strings = agentId.split(",");//{""}
boolean isSuccess = Arrays.asList(strings).contains("test");
}
这段代码不会出现空指针的问题,但是注意第3行代码,会生成一个大小为1的数组,这个元素的值为””。如果使用StringUtil工具类则会生成一个空数组,所以最好还是要使用工具类去分割字符串。
public static void whatIsProblem3() {
String agentId = "";
String[] strings = StringUtils.split(agentId,",");
boolean isSuccess = Arrays.asList(strings).contains("test");
}