Contents
  1. 1. 无参构造器

ArrayList有三个构造器,分别是无参构造器,传入一个整形参数的构造器,以及传入一个Collection实例的构造器。本文主要介绍前两种构造器。

无参构造器

示例代码:

1
2
3
4
5
6
7
8
9
public class ArrayListTest {
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("abc");
}
}

下面看调用构造器以及添加元素的代码

1
2
3
4
5
6
7
/**
* 用初始的10的容量大小构造一个空的list
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

从上述构造器可以看出,无参构造器只是很简单将常量DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋给成员变量elementData。这个成员变量和常量如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 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

从注释可以看出,DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个空的数组实例,用来作为默认大小的空List。它与EMPTY_ELEMENTDATA同时存在,是为了当第一个元素被添加到list中时,能算出要扩展多大的容量。

elementData是ArrayList中用于实际存储元素的数组。一个ArrayList实例的容量就是这个数组的长度。任何调用了默认构造器生成的ArrayList实例,都执行了elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,当第一个元素被添加到list中时,都会被扩展到默认的容量大小,即DEFAULT_CAPACITY(10)。

末尾添加元素的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
// 扩容之后将新增的元素加到末尾,同时将list的size加一。
elementData[size++] = e;
return true;
}

该方法首先调用了ensureCapacityInternal函数,用于确保容量足以添加一个元素。ensureCapacityInternal方法:

1
2
3
4
5
6
7
8
9
private void ensureCapacityInternal(int minCapacity) { // 插入“abc”时,minCapacity为1
// 当调用无参构造器时,初始存储元素的数组是DEFAULTCAPACITY_EMPTY_ELEMENTDATA
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 比较参数和默认容量大小,取大者作为扩展多容量
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // minCapacity变为10
}
ensureExplicitCapacity(minCapacity);
}

之后调用了ensureExplicitCapacity函数,继续扩展容量大操作:

1
2
3
4
5
6
7
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 检查目标容量是否大于当前数组的实际长度
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

上述方法继续调用grow函数,完成扩容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 容量扩充增量为当前数组容量大50%
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 若扩充后仍达不到目标容量,则直接使用目标容量作为新容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 若超过最大容量,则调用hugeCapacity函数
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 调用工具函数扩容,末尾用null补全
elementData = Arrays.copyOf(elementData, newCapacity);
}

从注释可知,该方法增长容量以确保list至少能保存传入参数大小数量多元素。之后,就可以插入元素“abc”。插入之后,list的size为1,容量为10.

Contents
  1. 1. 无参构造器