ArrayList
关于ArrayList
- ArrayList的长度可变:这里比较的是普通的数组你会发现普通数组没有扩容的方法,ArrayList继承了AbstractList因此继承了添加、删除、修改、遍历等方法并重写了他们。
- ArrayList具有随机访问功能:ArrayList实现了RandomAccess接口,但是这个接口并无内容,在自身类内部创建了内部类SubList实现RandomAccess接口并也实现增加删除等方法。
- ArrayList 能被克隆:ArrayList实现了Cloneable接口,但是这个接口也无内容,通过重写Object类的clone方法实现。
- ArrayList支持序列化:ArrayList实现了Serializable接口,但这个接口仍然是个空接口,对应的是writeObject方法。
*空接口起标识作用,告诉程序实现了它的对象具有某某功能
继承关系图
图源:参考资料1
通过各IDE查看源码可看到
每个类都具有属性和方法,首先介绍ArrayList的几个属性
/**
*序列化id
*/
private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity.
* 初始化时默认的大小
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
* 空对象共享的空数组对象(结合后面的初始化方法我理解为当你初始化时给定长度为0则这些对象都指向这个空对象)
*/
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.
* 共享空数组对象默认大小的空对象,我们用这个来区别EMPTY_ELEMENTDATA使我们知道扩大多少当第一个元素被添加时
* (结合后面的方法使用情况我认为这个是你使用无参构造函数初始化对象时该对象指向这个空对象)
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
* 是存储ArrayList元素的数组缓冲区,ArrayList的容量就是这个数组缓冲区的长度,任何指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA的空数组当被添加了第一个元素时容量会扩大为DEFAULT_CAPACITY
* (就是说这是真正存东西的地方,如果你用无参构造函数初始化对象然后往里面加东西那么它的容量会变成10)
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*当前数组长度
* @serial
*/
private int size;
然后看看三个构造方法
/**
* Constructs an empty list with the specified initial capacity.
* 用制定的容量大小创建一个空白的数组(这就是我们常用的方法之一,如:List arrList = new ArrayList(10);)
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 这行看出指定长度为0则共享EMPTY_ELEMENTDATA这个空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
* 创建一个容量为10的空白的数组(大家会觉得奇怪明明DEFAULTCAPACITY_EMPTY_ELEMENTDATA是空的又没有指定长度,可见方法ensureCapacity)
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
* 构建一个数组包含一个指定集合中的元素,这些元素被集合的遍历器按顺序返回
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)(见参考资料3,4此处无法链接)
// 例如使用Arrays.asList("String")方法得到一个List<String>数组后在使用toArray方法返回的不是Object[]而是String[]
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
参考资料:
-
知乎用户 Lyon 的文章Java集合—List—继承关系
-
CSDN用户 Fighter168 的文章ArrayList源码分析(基于JDK8)
-
博客园用户 长河落日圆 的文章利用Jdk 6260652 Bug解析Arrays.asList(学习笔记)
-
收录于Oracle的官方描述JDK-6260652 : (coll) Arrays.asList(x).toArray().getClass() should be Object[].class