![b7bf71ce40de2eba9a71301143940ed4.png](https://i-blog.csdnimg.cn/blog_migrate/43ee54b5f8f708a9cc9be906f89ee538.png)
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
ArrayList 继承于AbstractList,实现了List接口,其实AbstractList 已经实现过List接口,这里重复实现使得接口功能更加清晰,JDK中很多类都是如此。
其中Cloneable接口是克隆标记接口,Serializable序列化标记接口,需要clone和序列化功能必须实现这两个接口,而RandomAccess,单纯是一个标志接口 ,该接口表示该类支持快速随机访问,且在循环遍历时for循环的方式会优于用迭代器。
1.成员变量
// 默认初始容量
private static final int DEFAULT_CAPACITY = 10;
// 空数组实例,初始容量为0或者传入集合为空集合(不是null)时使用
private static final Object[] EMPTY_ELEMENTDATA = {};
// 空数组示例,无参构造时使用
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// ArrayList内部数据容器
transient Object[] elementData; // non-private to simplify nested class access
// 实际元素数量
private int size;
在ArrayList中,主要有五个成员变量。DEFAULT_CAPACITY表示初始容量大小,即在我们初始化ArrayList时不指定容量大小, 默认容量将会是10,Object[] elementData 则是ArrayList内部实际存储对象的容易,也就是我们常说的ArrayList是数组实现的。
在1.8中,空数组分为了两类情况,EMPTY_ELEMENTDATA 与 DEFAULTCAPACITY_EMPTY_ELEMENTDATA,在标记空数组的时候区分了不同的情况。
2.构造方法
ArrayList有三个构造方法,指定容量的ArrayList(int initialCapacity) ,无参构造ArrayList() 以及传入集合的ArrayList(Collection extends E> c)。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
最简单的莫过于无参构造,直接赋值为空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA。其实对于常说的默认容量10,是在第一次添加元素调用add()方法时处理的,并不是构造方法中。
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);
}
}
对于传入容量的构造方法,当传入参数 > 0时,直接初始化对应容量的数组,参数类型为int,也即ArrayList的最大初始容量不能超过Integer.MAX_VALUE,事实上ArrayList的最大容量也只能是Integer.MAX_VALUE。而初始容量传入0,会赋值为空数组EMPTY_ELEMENTDATA。如果 < 0,这个显然的不允许了,直接IllegalArgumentException
public ArrayList(Collection extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
集合构造时,没有进行null校验,也就是说如果传入null,直接就会NPE异常。集合构造的逻辑也很简单,当传入集合不为空时,调用Arrays.copyOf进行复制,并且容量 size为传入大小,而传入集合为空,则赋值为空数组EMPTY_ELEMENTDATA。
3.添加元素
ArrayList在添加元素时,都会进行容量确认,可能会涉及到扩容,数组复制,所以效率相对较低。同时在添加元素时,ArrayList并未对元素本身进行校验,所以是允许集合中存在null的情况。