从Java ArrayList 学习泛型设计
ArrayList的泛型设计分析
ArrayList是Java集合框架中一个非常重要的类,它巧妙地结合了泛型和Object数组来实现类型安全和高效的元素存储。下面我们来详细分析其设计的巧妙之处:
泛型声明与内部数组
源码位置: ArrayList.java
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {// ...transient Object[] elementData; // non-private to simplify nested class access// ...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);}}}
- 使用泛型参数
E
表示列表中存储的元素类型 - 内部采用
Object[]
数组存储元素(可容纳任意类型对象)
类型安全的实现
虽然内部使用 Object
数组存储元素,但通过泛型机制确保类型安全。在元素访问时,通过强制类型转换将 Object
转换为泛型类型 E
:
@SuppressWarnings("unchecked")
E elementData(int index) {return (E) elementData[index]; // 强制类型转换(编译器无法运行时验证类型安全)
}public E get(int index) {Objects.checkIndex(index, size);return elementData(index);
}
@SuppressWarnings("unchecked")
用于抑制编译器对类型转换的警告
添加元素的实现
public boolean add(E e) {modCount++;add(e, elementData, size);return true;
}private void add(E e, Object[] elementData, int s) {if (s == elementData.length)elementData = grow();elementData[s] = e; // 直接存储泛型元素(依赖类型擦除特性)size = s + 1;
}
- 利用Java泛型类型擦除特性:运行时所有泛型类型均视为
Object
类型
迭代器中的泛型处理
private class Itr implements Iterator<E> {// ...@SuppressWarnings("unchecked")public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i]; // Object→泛型类型转换}// ...
}
toArray方法的泛型处理
源码位置: ArrayList.java
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {if (a.length < size)// 创建与输入数组运行时类型相同的新数组return (T[]) Arrays.copyOf(elementData, size, a.getClass());System.arraycopy(elementData, 0, a, 0, size);if (a.length > size)a[size] = null;return a;
}
- 通过传入数组类型
T
确定返回数组类型,并执行Object[]
到指定类型数组的转换
sort方法
巧妙结合泛型与Object数组实现类型安全且高效的排序。
private void sortRange(Comparator<? super E> c, int fromIndex, int toIndex) {final int expectedModCount = modCount; // 记录初始修改计数Arrays.sort((E[]) elementData, fromIndex, toIndex, c); // 调用JDK排序if (modCount != expectedModCount) throw new ConcurrentModificationException(); // 并发修改检查
}
底层存储:
elementData
是Object[]
类型数组,实际存储列表的所有元素。类型转换:
将elementData
强制转换为E[]
后传入Arrays.sort
。
安全性保障:ArrayList内部严格保证只存储类型E
的元素,因此运行时转换是安全的(依赖泛型擦除后实际为Object[]
的特性)。【注意null也是类型E,因此new Object[cap]创建的也是E[ ]】性能优化:
直接复用JDKArrays.sort
的高效实现,通过泛型擦除在编译期保证类型安全,运行时无额外开销。