今天看到一個如博客題目問題,想着應該會初始化吧,不然這個構造方法時幹嘛的是吧。
話不多說,直接上代碼,看下就好了。
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)
有點意外,有點驚喜,傳入了初始值了,數組大小竟然還是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
,並判斷是否合法(大於等於0)。大於等於0時,初始化了數組的數組內容。
/**
* 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的結果。