增强 for 循环本身不抛异常,问题在于循环体内调用 remove() 等结构修改方法;Arrays.asList() 返回固定大小列表,不支持 add/remove,但允许 set() 和 setValue()(若元素支持)。

增强 for 循环遍历 Arrays.asList() 为什么会抛 UnsupportedOperationException
因为 Arrays.asList() 返回的是一个固定大小的、底层由原始数组支撑的 List 实现,它不支持结构修改(如 add()、remove()),但增强 for 循环本身不会调用这些方法——问题出在你循环体里偷偷改了集合。
常见错误现象:for (String s : list) { list.remove(s); } 看似只是读,实则触发了迭代器的 remove(),而该实现直接抛 UnsupportedOperationException。
- 使用场景:想边遍历边过滤掉某些元素,误以为增强 for 支持“安全删除”
- 真正安全的做法是用
Iterator的remove(),或先收集待删元素再批量操作 -
Arrays.asList()返回的列表不可变,但允许修改已有元素(set()是 OK 的)
用 Stream.toList() 或 new ArrayList() 替换不可变源
Java 16+ 的 Stream.toList() 返回的是不可修改的 List(和 Arrays.asList() 行为一致),不是更安全的替代;真要可变,得显式构造。
- 正确复制方式:
new ArrayList(Arrays.asList("a", "b"))或List.copyOf(list)(后者仍不可变) -
List.copyOf()在 Java 10+ 引入,返回不可变副本,适合只读场景,性能略好(无防御性拷贝) - 如果原集合来自
Collections.unmodifiableList(),增强 for 安全,但任何修改尝试都会立即失败,别指望“试试看”
增强 for 循环本身从不修改集合,陷阱全在循环体内
增强 for 编译后就是标准的 Iterator 遍历,它不提供修改能力。所谓“安全”,仅指语法上不让你写 list.add() 这类操作——但你可以手动调用,也能通过闭包、引用等间接触发。
立即学习“Java免费学习笔记(深入)”;
- 典型坑:
for (Map.Entry e : map.entrySet()) { e.setValue(...); }——setValue()是允许的,但若entrySet()来自不可变Map(如Map.of()),就会立刻报错 - 参数差异:增强 for 的变量是集合元素的副本(对引用类型是引用副本),修改该变量本身不影响集合,但调用其方法可能影响
- 性能影响:没有额外开销,和手写
Iterator几乎等价;但频繁创建新集合来规避不可变限制,反而增加 GC 压力
判断集合是否真正可变,不能只看声明类型
接口是 List,运行时可能是 UnmodifiableRandomAccessList、Arrays$ArrayList 或 ArrayList——三者都实现 List,但行为天差地别。
- 调试建议:打断点后看实际类名,或用
list.getClass().getName()快速识别 - 兼容性注意:Spring 的
@RequestParam List<string></string>、Jackson 反序列化的集合,默认都可能是不可变实现,别默认能add() - 最容易被忽略的一点:不可变集合的子集操作(如
subList())返回的仍是不可变视图,增强 for 里调用clear()同样炸


















