本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接
前言
看到这个问题的时候,一眼看去,这么简单的问题,为何会问。其实,转眼一想,是的,这个还是很具有迷惑性的问题。对于初学者,来说,这块确实容易迷失。很多人不理解。
那么,我们就来看看这个问题,对它进行一次深入的解剖!
问题复现
定义一个初始化大小为10的集合
ArrayList<Integer> arr=new ArrayList<Integer>(10);
使用集合方法进行添加元素
arr.add(5,10)
我们看一下结果
迷惑的地方出现了,为啥会报越界呢?我们明明已经初始化了集合的大小为10,add方法,添加的索引为5,还不到10。
估计初学者已经懵逼,我们就来详细看看咋回事。
问题解析
首先,我们来看集合的add方法,是怎么定义的
/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
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++;
}
方法,确实提供了两个参数,索引位置,元素值。
通过了解注释,我们可以看到,将指定的元素插入此列表中的指定位置。 将当前在该位置的元素(如果有)和任何后续元素右移(将其索引添加一个)。
/**
* A version of rangeCheck used by add and addAll.
*/
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
观察方法rangeCheckForAdd
我们,可以了解到,该方法,判断的是index和size的比较
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
那么,我们看到之前异常截图,显示Size为0,这是为啥来,我们好像已经初始化了大小。
看来,问题,在于初始化。我们就来看看,我们自定义集合时,到底干了点什么。
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
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);
}
}
我们发现,初始化时,指定的是initialCapacity 初始化容量大小,看出来,并不是size大小。
问题明朗了,我们混淆了Size和Capacity的概念。
问题总结
size 是集合包含元素的数量
capacity 是定义集合能够包含元素的数量
初学者,需要更细心的观察源码的实现。