for (元素類型T 變量名O : 循環對象) {
// 操作 O
}
循環對象可為:數組、實現 Iterable 的集合(List、Set 等)。
List<String> list = Arrays.asList("A", "B", "C");
for (String s : list) {
System.out.println(s);
}
foreach 僅能遍歷,無法在遍歷過程中增刪集合元素,否則拋 ConcurrentModificationException。for 循環配合索引可安全修改。
// 錯誤示例
for (String s : list) {
if ("B".equals(s)) list.remove(s); // 拋異常
}
// 正確做法:使用 Iterator 或倒序 for 循環
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if ("B".equals(it.next())) it.remove();
}
看代碼預測輸出:
List<Integer> list = new ArrayList<>();
list.add(1); list.add(2); list.add(3);
for (int i = 0, size = list.size(); i < size; i++) {
System.out.println(list.get(i));
if (i == 1) list.remove(0); // 刪除第一個元素
}
輸出:1、2、3(只有 3 次循環)。
原因:size = list.size() 在循環開始前只計算一次(值為 3),循環中 list 縮短但 size 不變,導致索引越過實際大小。

編譯器將 foreach 編譯為:
iaload 等指令)。iterator() 獲取迭代器,循環調用 hasNext()、next()。這就是為什麼 foreach 不能修改集合結構——迭代器的 remove() 是唯一安全方式,而 foreach 隱藏了迭代器引用。
| 場景 | 推薦方式 | 原因 |
|---|---|---|
| 數組遍歷 | for / foreach 均可 | foreach 編譯為索引訪問,無額外開銷 |
| ArrayList 遍歷 | for (int i=0; i| 隨機訪問 O(1),避免迭代器對象創建 | |
| LinkedList 遍歷 | foreach / Iterator | 順序訪問,foreach 內部用迭代器避免 O(n²) |
| 需修改結構 | Iterator / ListIterator | foreach 不支持,for 需小心索引同步 |
foreach 是讀取遍歷的利器,代碼簡潔、語義清晰;但遇到修改集合、需索引、高性能數組隨機訪問時,傳統 for 或 Iterator 更合適。理解「條件求值一次」與「編譯為迭代器」兩大底層機制,能避開 90% 的循環陷阱。