java迭代器采用内部类是因需直接访问容器私有成员(如elementdata、modcount),保障封装性与fail-fast机制;非静态内部类持外部引用以实时校验状态,静态内部类则用于仅依赖公开api的场景。

Java 迭代器源码中,内部类是最主流、最自然的设计方式——它不是权宜之计,而是基于封装性、访问权限和语义耦合的理性选择。
为什么用内部类而不是独立类?
核心原因在于:迭代器必须紧密依赖容器的内部状态(如数组引用、size、modCount),而这些字段通常被声明为 private。独立类无法直接访问,强行暴露会破坏封装;内部类则天然享有对宿主类所有成员(包括私有字段和方法)的访问权。
- ArrayList 的
Itr内部类可直接读取elementData[]、size和modCount - LinkedList 的
ListItr可直接操作first、last节点和size - HashMap 的
KeyIterator等能直接遍历Node[] table和处理红黑树结构
内部类怎么组织才合理?
典型实现采用 私有静态内部类 + 非静态内部类混合使用:
- 非静态内部类(如 ArrayList.Itr):需持有外部类实例引用,用于实时读取动态状态(如当前 size、modCount 检查)
- 静态内部类(如 HashMap.KeyIterator):若仅需访问容器的公开 API 或通过参数传入必要数据,可用 static 减少内存开销(避免隐式持外部类引用)
- 多数 JDK 实现倾向非静态,因为要支持 fail-fast 机制——必须能感知外部容器是否被并发修改
关键设计细节不能漏
一个健壮的内部迭代器类通常包含以下要素:
-
游标位置字段(如
cursor、lastRet、nextIndex):记录当前遍历进度 -
快速失败校验:在
hasNext()和next()中检查modCount == expectedModCount -
remove() 的状态约束:只允许在调用过
next()后执行,且不可连续调用两次 -
泛型与类型擦除适配:内部类声明为
class Itr implements Iterator<e></e>,利用外部类的类型参数
实际代码片段示意(简化版 ArrayList.Itr)
注意:这不是完整源码,仅展示结构意图
private class Itr implements Iterator<e> {
int cursor = 0; // 下一个元素索引
int lastRet = -1; // 上一次返回的索引
int expectedModCount = modCount; // 快速失败快照
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification(); // 校验是否被修改
try {
E element = (E) elementData[cursor];
lastRet = cursor++;
return element;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}</e>Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











