public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>(10);
System.out.println(list.size());
list.add("hello");
System.out.println(list.size());
list.set(2, "hah");
System.out.println(list.size());
}
输出结果如下
0
1
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:657)
at java.util.ArrayList.set(ArrayList.java:448)
at com.lin.test.other.TestLearning.main(TestLearning.java:14)
看下源码:
/**
* 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);
}
}
该构造方法,初始化了数组的数组内容。
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
但是这里没有关系到数组的大小(size)。那么对于int属性的size来说,没有指定其大小的话,默认是0,直接打印list.size(),显示为0。
接着看下set方法:
/**
* Replaces the element at the specified position in this list with
* the specified element.
*
* @param index index of the element to replace
* @param element element to be stored at the specified position
* @return the element previously at the specified position
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
首先是检查放入的位置跟size的大小,index大于size则抛出IndexOutOfBoundsException异常。
还不明白的话,那就看下elementData的注释,elementData作为存储ArrayList元素的数组缓冲区,ArrayList的容量是这个数组缓冲区的长度。注意,这里提到的是容量capacity,而size则是:the size of the ArrayList (the number of elements it contains).数组中包含元素的个数。
可见,当使用ArrayList(int initialCapacity)的时候,只是指定了缓冲区数组的大小, 跟数组的大小size并没有什么关系。所以出现了初始化之后,打印数组的size仍然为0的结果。