只读迭代器需通过接口契约、实现约束与运行时防护切断修改通道:不实现或抛出UnsupportedOperationException;不暴露底层引用;集合侧拒绝可变入口;命名与类型强化不可变语义;并发下依赖快照或不可变底座。

设计只读迭代器的核心是切断外部对集合数据的修改通道,同时明确表达“不可变”语义。这不是靠文档说明或约定,而是通过接口契约、实现约束和运行时防护共同达成。
让迭代器不提供任何修改能力
最直接有效的方式是彻底不实现 remove() 方法,或统一抛出异常。Java 标准做法是让自定义迭代器的 remove() 方法直接抛出 UnsupportedOperationException,这是 JDK 中绝大多数只读视图(如 Collections.unmodifiableList() 返回的迭代器)的标准行为。
- 不要在迭代器中暴露集合引用、数组、节点指针等底层结构
- 避免在
next()中返回可变对象的原始引用——若元素本身可变(如StringBuilder),应考虑返回不可变包装或深拷贝副本 - 如果集合本身支持结构修改(如增删元素),迭代器绝不参与这些操作;所有遍历逻辑只读取,不触发任何写路径
集合侧配合:拒绝暴露可变入口
只读迭代器要真正安全,集合类本身必须守好边界。即使迭代器再谨慎,若集合仍通过 getData()、getInternalList() 等方式返回可变引用,整个只读承诺就失效了。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 集合类不提供返回内部容器(如
ArrayList、Node[])的 public 方法 - 若需对外提供“视图”,应返回
unmodifiableXXX包装器,或使用Arrays.asList()+ 不可变语义构造(注意后者仅对数组长度固定有效) - 实现
Iterable<t></t>接口时,iterator()方法返回的必须是前述严格只读的迭代器实例
增强语义表达:用类型与命名传递意图
Java 没有原生 readonly 关键字,但可通过命名和泛型辅助传达设计意图,降低误用概率。
立即学习“Java免费学习笔记(深入)”;
- 迭代器类名体现只读性,例如
ReadOnlyBookIterator、SnapshotIterator - 集合类名或文档中明确标注 “immutable view” 或 “read-only access only”
- 必要时可定义专用接口继承
Iterator<t></t>并注释为@Immutable或@ReadOnly(配合静态分析工具识别)
应对并发场景:快照或不可变底座
单线程只读还不够——多线程下若集合被其他线程修改,迭代器可能看到不一致状态。真正安全的只读需配合数据稳定性机制。
- 采用
CopyOnWriteArrayList:其迭代器天然基于创建时刻的快照,遍历时绝对不反映后续变更,且remove()直接抛异常 - 基于不可变集合构建(如
ImmutableListfrom Guava 或List.of()):底层数组不可更改,迭代器只需简单线性遍历,无并发风险 - 若自定义复杂结构(如树),迭代器应在构造时捕获结构快照(如序列化节点路径、复制关键状态),而非持有所属集合的实时引用

















