ArrayList(int initialCapacity)會不會初始化數組大小?

今天看到一個如博客題目問題,想着應該會初始化吧,不然這個構造方法時幹嘛的是吧。

話不多說,直接上代碼,看下就好了。

	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的結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章