以下解析基于JDK8.0

ArrayList的继承关系如下:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

ArrayList的底层是用数组实现的:

transient Object[] elementData; // non-private to simplify nested class access

ArrayList的默认初始化大小是10:

/**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

比如说ArrayList mylist = new ArrayList(); mylist.add(new Object());在这种情况下,第一次add一个元素,则mylist的容量扩展为10(上面这个默认初始化大小为10貌似容易引起误会,以为是ArrayList对象刚new出来容量就初始化为10了,其实并没有。不过在初始化ArrayList的时候确实可以调用一个带参数的构造函数以指定初始化的容量:如ArrayList mylist = new ArrayList(20);这样的话对象一new出来容量就为20了,两个构造函数如下:)

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);
        }
    }
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

上面出现的两个常量如下所示:

/**
     * 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 = {};

两个常量都是static final类型的空数组,之所以要有第二个常量DEFAULTCAPACITY_EMPTY_ELEMENTDATA是为了能够在第一次add元素需要进行扩容的时候判断是否将容量扩充为默认初始化容量10(如果这个容量足够的话)。上面代码中的注释说的就是这个意思。我们可以看一下add方法的代码:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

ArrayList的扩容机制是每次增长为原容量的1.5倍,具体代码如下:

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

从代码中可以看出,如果一次扩容还达不到minCapacity的时候则新容量直接赋值为minCapacity(所以扩容的增长路线并不一定是10,15,22……这样增长的,而且初始化的时候也还可以指定容量),同时从上述代码最后一行也可以看出来,所谓的扩容就是把数组元素复制到一个更大空间的数组中。

再来看一下remove方法:

public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

注意到在查找要删除的元素时采用的是equals方法,因此添加到ArrayList中的元素所属的类(尤其是我们自定义的类)最好需要重写一下equals方法,否则得到的结果可能并不是你想要的。从上面代码我们还能看出来的一点是ArrayList里面可以包含null元素,为了避免出现空指针异常,上面的代码分别处理了元素为null以及不为null的情况。

ArrayList中还包含很多其他的方法,在这里就不一一列举了。水平有限,如有不当之处,还望指正!