ArrayList<String> list = new ArrayList<>();
首先我们先创建初始化一个ArrayList,在初始化时,会调用ArrayList的构造方法,有几个要记住的点,如下:
请区别开size和CAPACITY(容量),容量相当于一个杯子容量为500ml,size相当于你实际装进去的水。
默认初始容量:
private static final int DEFAULT_CAPACITY = 10;
用于空实例的共享空数组实例:
private static final Object[] EMPTY_ELEMENTDATA = {};
用于默认大小的空实例的共享空数组实例:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
存储 ArrayList 元素的数组缓冲区:
transient Object[] elementData;
注意: ArrayList 的容量就是这个数组缓冲区的长度。当添加第一个元素时,任何具有 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList 都将扩展为 DEFAULT_CAPACITY
ArrayList 的大小(它包含的元素数量):
private int size;
好了,了解了以上之后,我们调用构造方法:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
请注意,elementData是个Object的数组,只被声明,没有被初始化,该构造方法相当于把一个空的Object数组赋给elementData,size为0。所以该ArrayList的容量为默认初始容量DEFAULT_CAPACITY = 10
这样,一个ArrayList就被初始化好了,现在我们调用它的add方法。
list.add("1");
通过Debug模式,我们会追溯其源码。
然后进入到ArrayList的add方法中。
这里面又调用了ensureCapacityInternal方法,把size+1传进去,相当于把原来的size(此时为0)+1传进去。
我们进去再看看ensureCapacityInternal方法
此时,最小容量为1,然后进入if语句中。还记得吗,elementData在我们初始化ArrayList的时候,构造方法把等号右边这个数组赋给了它,所以判断为true
现在,取DEFAULT_CAPACITY与最小容量的最大值,并且再赋给minCapacity,此时DEFAULT_CAPACITY==10,所以minCapacity==10
然后进入ensureExplicityCapacity方法中,把minCapacity传进去。
modCount++这行代码暂且可以不管,与本次扩容无关,我们直接看下面的代码
进行一次比较,minCapacity此时为10,elementData这个数组的长度,因为现在为空,所以elementData.length ==0,判断为true,运行下面的grow方法,并且把minCapacity传进去
oldCapacity是原来的容量 = elementData.length = 0,
newCapacity是新容量 = oldCapacity + (oldCapacity >> 1) (位运算符,向右移1位可以理解为除以2)
所以newCapacity = 0
进行比较,newCapacity显然小于minCapacity(10)
所以把最小容量赋值给新容量,newCapacity =10;
再进行一次比较,新容量是否大于ArrayList所定义的最大限量的容量,具体值为图所示,显然为false,所以newCapacity = hugeCapacity(minCapacity)不用执行。
然后,执行Arrays.copyOf()方法,该方法会复制指定的数组,截断或填充空值(如有必要),使副本具有指定的长度,相当于把elementData的length扩充为10,并且填充默认值。
至此,扩容完成。
最后返回到add方法中,将elementData的size(请区别现在的size变量和上述的length),当前size为0,所以把e(是我们传进来的String "1") 赋给 坐标为elementData[0] 的元素,然后ArrayList的size++。
还有一些未补充和没说完整的,以后再补充。