Java增强for循环处理集合对象的行为疑问:代码结果不符预期
为什么增强for循环里修改集合引用还是会遍历原元素?
嘿,这个问题我刚学Java的时候也懵过!先把你的代码贴出来方便分析:
public static void main(String[] args) { ArrayList<String> a = new ArrayList<>(); a.add("1"); a.add("2"); for(String str: a){ a = new ArrayList<>(); System.out.println(str); } }
你原本以为输出是1 null,但实际是1 2,核心原因是增强for循环的底层逻辑和你想的不一样:
- 增强for循环(也叫for-each循环)本质上是依赖集合的迭代器(
Iterator)实现的。当你进入这个循环的瞬间,JVM会先调用a.iterator()获取一个绑定到当前a指向的原始ArrayList对象的迭代器,这个迭代器内部已经保存了要遍历的元素列表(就是["1","2"])。 - 后面你在循环里把
a重新赋值为新的空ArrayList,只是改变了变量a的引用指向,完全没影响到之前已经创建好的那个迭代器——它自始至终都盯着最初的那个包含"1"和"2"的集合。 - 所以第一次循环取出"1"打印,第二次迭代器继续从原集合取出"2"打印,直到原集合的元素遍历完,循环就结束了。
举个通俗的例子:你手里拿着一张写着地址的纸条(变量a),上面写着你家的地址(原始ArrayList)。然后你找了个快递员(迭代器),告诉他去这个地址取东西。之后你把纸条上的地址改成了邻居家(a指向新ArrayList),但快递员还是会按之前告诉你的地址去你家取东西,不会管你纸条上的地址变了。
如果想验证这个逻辑,你可以试试在循环里修改原集合的内容(比如a.remove(str)),这时候迭代器会检测到原集合被修改,直接抛出ConcurrentModificationException——这才是迭代器会关心的变化,而变量引用的改变它根本不care。
内容的提问来源于stack exchange,提问作者Namrata Shukla
相关产品推荐
相关产品推荐

