注意ArrayList的数组越界异常

我们都知道ArrayList的底层是由数组实现的,并且数组初始容量为10,数组满时会以1.5倍的倍率进行扩容,但是调用remove()方法删除元素时,数组并不会缩小容量。换言之,ArrayList中数组的长度只增不减,在第一次往ArrayList中添加元素之后,数组容量就一定>=10(new ArrayList对象时,数组还没有真正创建,数组是在第一次向ArrayList中添加元素时创建的)

但是由于ArrayList在数组的基础上进行了很多封装,所以很多数组的特性并不能简单套用,比如今天我就犯了一个经验主义错误。

我在写一个删除方法的单元测试时,Assert条件本应写成下面这样

Assert.assertTrue(list.isEmpty());

其中list是执行删除操作后按原条件从数据库查询的结果,如果删除成功,list应该为空。但是因为我在复制粘贴别的单元测试的代码时,复制来的Assert条件是这样的

Assert.assertNull();

我脑子中做了这样的转换:
因为:ArrayList等价于数组
所以:ArrayList为空等价于Array[0]==null
所以我把Assert条件写成了下面这个样子

Assert.assertNull(list.get(0));

结果自然是Assert失败,发生了IndexOutOfBoundsException,索引越界异常。如果操作的是数组,那么数组索引越界异常只会在操作的索引超过数组实际长度时发生。

@Test
public void test() {
    Object[] array = new Object[10];
    System.out.println(array[0]); // 不会抛异常
    System.out.println(array[10]); // 会抛异常
}

在这里插入图片描述

有这种区别原因就在于,ArrayList对内部的数组做了封装,在操作数组前会验证size()的大小,无论内部数组实际的长度是多少,对ArrayList所能操作的索引值不能超过size()方法的返回值,否则就会抛出异常。

@Test
public void test() {
    ArrayList<Object> list = new ArrayList<>(20);
    System.out.println("此时ArrayList.size()返回值为:" + list.size());
    list.add(0, new Object()); // 不会抛出异常
    System.out.println("此时ArrayList.size()返回值为:" + list.size());
    list.add(10, new Object()); // 会抛出异常
}

在这里插入图片描述

总结:
这次的问题提醒我
1、复制粘贴代码有时候不光不能省事,还会造成更多的错误和麻烦
2、写代码一定要规范,不要想当然,把数组的常识生硬地套用到ArrayList上,就会出问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值