Java 集合框架中,ArrayList 繼承 AbstractList,HashMap 繼承 AbstractMap。為什麼不直接實現 List/Map 接口,而是中間插入抽象類?
| 特性 | Interface (Java 7 及之前) | Abstract Class |
|---|---|---|
| 方法實現 | **不能**有方法體(僅常量、抽象方法) | **可以**有具體方法實現 |
| 字段 | 僅 static final 常量 | 可有實例字段、構造函數 |
| 繼承關係 | 多實現 (implements) | 單繼承 (extends) |
| 訪問修飾符 | 隱式 public | 可 protected/private/package-private |
AbstractList 實現了基於 iterator() 和 size() 的 **30+ 個便利方法**:
// AbstractList 部分源碼
public boolean add(E e) { add(size(), e); throw new UnsupportedOperationException(); }
public E get(int index) { throw new IndexOutOfBoundsException(); }
public boolean contains(Object o) { return indexOf(o) >= 0; }
public int indexOf(Object o) {
ListIterator it = listIterator();
while (it.hasNext()) if (Objects.equals(o, it.next())) return it.previousIndex();
return -1;
}
// 子類僅需實現 iterator()、size()、get(int)、set(int,E)、add(int,E)、remove(int)
// 即可獲得 addAll、removeAll、retainAll、equals、hashCode、toString、subList 等完整功能
AbstractMap 提供 entrySet()、keySet()、values() 的**標準視圖實現**,子類無需重複編寫迭代器邏輯:
// AbstractMap 簡化視圖實現
public Set keySet() {
Set ks = keySet;
return (ks != null) ? ks : (keySet = new KeySet());
}
final class KeySet extends AbstractSet {
public Iterator iterator() { return new KeyIterator(); }
public boolean contains(Object o) { return containsKey(o); }
public int size() { return AbstractMap.this.size(); }
}
抽象類通過文檔明確規定:**子類必須實現的最小方法集**:
AbstractList:get(int)、size()(隨機訪問)或 listIterator()(順序訪問)AbstractMap:entrySet()AbstractSet:繼承 AbstractCollection,需實現 iterator()、size()這比單純閱讀接口文檔更具體、更易落地。
size() 和 iterator() 不在抽象類中實現?因為它們是「數據結構核心」,完全依賴具體實現方式,無法提供通用默認實現。
| 實現類 | size() 實現 | iterator() 實現 |
|---|---|---|
ArrayList | 返回 size 字段 (O(1)) | 返回 Itr 內部類,基於數組索引遍歷 |
LinkedList | 返回 size 字段 (O(1)) | 返回 ListItr,基於雙向鏈表節點遍歷 |
HashMap | 返回 size 字段 | 遍歷 table 數組 + 鏈表/紅黑樹節點 |
TreeMap | 返回 size 字段 | 中序遍歷紅黑樹節點 |