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 底层就是一个数组,其中:
DEFAULT_CAPACITY 表示数组的初始大小,默认为 10
size 表示当前数组的大小
modCount 统计当前数组被修改的版本次数,每次数组结构有变动时,例如调用 add()、remove(),modCount 的值就会跟随 +1。
ArrayList 其他特点,也是注释上的说明:
ArrayList 内允许放入 null 值
新增元素时会有扩容机制
是非线程安全的
增强 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 版本中修复。
评论