深入學習JDK原始碼系列之、ArrayList
阿新 • • 發佈:2020-08-04
## 前言
JDK原始碼解析系列文章,都是基於JDK8分析的,雖然JDK15馬上要出來了,但是JDK8我還不會,我...
## 類圖
![](https://img.iisheng.cn/array-list-diagram.png)
- 實現了`RandomAccess`介面,可以隨機訪問
- 實現了`Cloneable`介面,可以克隆
- 實現了`Serializable`介面,可以序列化、反序列化
- 實現了`List`介面,是`List`的實現類之一
- 實現了`Collection`介面,是`Java Collections Framework`成員之一
- 實現了`Iterable`介面,可以使用`for-each`迭代
## 屬性
```Java
// 序列化版本UID
private static final long
serialVersionUID = 8683452581122892189L;
/**
* 預設的初始容量
*/
private static final int
DEFAULT_CAPACITY = 10;
/**
* 用於空例項的共享空陣列例項
* new ArrayList(0);
*/
private static final Object[]
EMPTY_ELEMENTDATA = {};
/**
* 用於提供預設大小的例項的共享空陣列例項
* new ArrayList();
*/
private static final Object[]
DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 儲存ArrayList元素的陣列緩衝區
* ArrayList的容量,是陣列的長度
*
* non-private to simplify nested class access
*/
transient Object[] elementData;
/**
* ArrayList中元素的數量
*/
private int size;
```
> 小朋友,你四否有很多問號?
1. 為什麼空例項預設陣列有的時候是`EMPTY_ELEMENTDATA`,而又有的時候是`DEFAULTCAPACITY_EMPTY_ELEMENTDATA`
2. 為什麼`elementData`要用`transient`修飾?
3. 為什麼`elementData`沒有被`private`修飾?難道正如註釋所寫的**non-private to simplify nested class access**
> 帶著問題,我們繼續往下看。
## 構造方法
### 帶初始容量的構造方法
```Java
/**
* 帶一個初始容量引數的構造方法
*
* @param initialCapacity 初始容量
* @throws 如果初始容量非法就丟擲
* IllegalArgumentException
*/
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);
}
}
```
- 如果`initialCapacity > 0`,就建立一個新的長度是`initialCapacity`的陣列
- 如果`initialCapacity == 0`,就使用EMPTY_ELEMENTDATA
- 其他情況,`initialCapacity`不合法,丟擲異常
### 無參構造方法
```Java
/**
* 無參構造方法 將elementData 賦值為
* DEFAULTCAPACITY_EMPTY_ELEMENTDATA
*/
public ArrayList() {
this.elementData =
DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
```
### 帶一個集合引數的構造方法
```Java
/**
* 帶一個集合引數的構造方法
*
* @param c 集合,代表集合中的元素會被放到list中
* @throws 如果集合為空,丟擲NullPointerException
*/
public ArrayList(Collection c) {
elementData = c.toArray();
// 如果 size != 0
if ((size = elementData.length) != 0) {
// c.toArray 可能不正確的,不返回 Object[]
// https://bugs.openjdk.java.net/browse/JDK-6260652
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(
elementData, size, Object[].class);
} else {
// size == 0
// 將EMPTY_ELEMENTDATA 賦值給 elementData
this.elementData = EMPTY_ELEMENTDATA;
}
}
```
- 使用將集合轉換為陣列的方法
- 為了防止`c.toArray()`方法不正確的執行,導致沒有返回`Object[]`,特殊做了處理
- 如果陣列大小等於`0`,則使用 `EMPTY_ELEMENTDATA`
> 那麼問題來了,什麼情況下`c.toArray()`會不返回`Object[]`呢?
```Java
public static void main(String[] args) {
List