AbstractList是一个抽象容器,其中有很多abstract方法便于子类实现。这个类主要实现了迭代器功能和定义了一系列容器的操作接口。
迭代器是一个内部类,这个内部类有三个字段:
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
第一个可以理解为游标,用于标识数组元素的第一个下标。
第二个也可以理解为游标,但是如果这个元素不存在,那么这个值就是-1.
第三个字段很重要,用于检测元素数组是否被修改的判断。如果数组在迭代过程中增加或删除,则可以直接检查出来,导致快速失败。
看看使用最多的方法:
检查是否还有下一个元素:
public boolean hasNext() {
return cursor != size();
}
判断逻辑简单粗暴,直接判断游标是否等于数组长度。如果等于,则没有下一个元素,如果不等于,说明还没有迭代到数组最后。
获取下一个元素:
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
这里先获取了游标,然后直接取游标对应的取值,然后返回。
看看迭代器最重要的一个方法:检查并发修改的内容。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
这个方法主要检查了从迭代器构造完成后数组的容量和迭代以后数组的容量是否相等,如果不相等,说明有其他线程修改了数组长度,这里会抛出一个ConcurrentModificationException同步修改异常,也就是经常说的快速失败(fast fail)。
在java并发编程实践中说,这种设计只是善意提醒了这个容器存在多线程操作,因为这个容器目前只支持单线程操作。当然,在这里捕捉的容器长度并不精确。