ArrayList源码分析-初始化

86 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

ArrayList源码分析-初始化

ArrayList是我们经常会用到的一个类,并且也属于面试常问的问题。

ArrayList底层结构

先看源码:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] EMPTY_ELEMENTDATA = {};
    transient Object[] elementData; // non-private to simplify nested class access
    private int size;

    ......
}

ArrayList底层就是一个数组,其中:

  1. DEFAULT_CAPACITY 表示数组的初始大小,默认为 10
  2. size 表示当前数组的大小
  3. modCount 统计当前数组被修改的版本次数,每次数组结构有变动时,例如调用add()、remove(),modCount的值就会跟随 +1。

ArrayList其他特点,也是注释上的说明:

  1. ArrayList内允许放入null值
  2. 新增元素时会有扩容机制
  3. 是非线程安全的
  4. 增强 for 循环,或者使用迭代器迭代过程中,如果数组大小被改变,会快速失败,抛出异常。

ArrayList的初始化方法

无参初始化,源码:

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

指定大小初始化,源码:

    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(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;
        }
    }

需要注意的是,其中ArrayList 无参构造器初始化时,默认大小是空数组,并不是大家常说的 10,10 是在第一次 add 的时候扩容的数组值。

初始化中的一个bug

在以上构造方法的指定初始数据初始化方法中,有一行注释 see 6260652,这是 Java 的一个 bug。

当初始化数据传入值不是Object类型时,转为Object,调用java.util.ArrayList#toArray()方法,得到Object数组,往Object数组赋值时会触发此bug,不过已经在java9版本中修复。