【Java源码分析】为什么不可以在指定默认容量的ArrayList对象中插入元素
问题描述
执行以下代码会报异常 java.lang.IndexOutOfBoundsException: Index: 5, Size: 0
@Test
public void test(){
ArrayList<Integer> list = new ArrayList<Integer>(10);
list.add(5, 1);
}
查看源码分析
当执行 ArrayList list = new ArrayList(10);时,会调用ArrayList的构造方法,其源码如下
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
可见,ArrayList确实是创建了长度为指定容量10的数组。
但是执行 list.add(5, 1); 时抛出了索引越界异常。
为什么无法在下标为5处插入元素呢?
我们来看看add的源代码
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
add 方法体中的第一行是 rangeCheckForAdd(index);
它是一个验证索引的方法,具体代码如下
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
当我们执行 list.add(5, 1);的时候,会把 5 传递给 index。
而此时,list中还没有元素,size = 0。
因此,index > size条件成立,就执行 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
解决办法
使用Integer数组操作,然后转换为ArrayList对象
@Test
public void test02(){
Integer[] array = new Integer[10];
array[5] = 1;
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(array));
System.out.println(list);
}
执行结果如下:
[null, null, null, null, null, 1, null, null, null, null]
参考:
ArrayList源代码