java -- 增强 for 循环

是什么

增强 for 循环是 JDK1.5 后引入 java 的一种语法,其目的主要是方便遍历集合中的元素。

干什么

对于集合的遍历,我们先看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
Collection<String> c = new ArrayList<String>();
c.add("I");
c.add("love");
c.add("java");

for(String str:c){
System.out.println(str);
}

输出为:
I
love
java

这种方法相对于以前的将集合转数组,抑或是通过迭代器遍历,都显得更为简单直接。

什么时候可以用

在 JDK 文档中指出,凡是实现了 iterable 接口的子类对象都可以使用增强 for 循环。

注意

如果我们在增强 for 中,同时修改了遍历集合,就会抛出 ConcurrentModificationException 异常。这里为深入了解其中机制,我们有必要知道增强 for 在遍历时,到底做了什么?

利用反编译工具 procyon.jar,我们对上述代码进行了反编译,过程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
rqsir@rqsir-TM1604:~/IdeaProjects/EnhancedForLoop/out/production/EnhancedForLoop$ java -jar /opt/procyon.jar -b EnhancedForLoopTest.class
public class EnhancedForLoopTest {
public void EnhancedForLoopTest() {
invokespecial:Object(Object::<init>, this:EnhancedForLoopTest)
}

public static void main(java.lang.String[] args) {
c : Collection<String>
var_2_29 : Iterator<String>
str : String

c = initobject:ArrayList<String>[expected:Collection<String>](ArrayList<E>::<init>)
invokeinterface:boolean(Collection<String>::add, c:Collection<String>, ldc:String("I"))
invokeinterface:boolean(Collection<String>::add, c:Collection<String>, ldc:String("love"))
invokeinterface:boolean(Collection<String>::add, c:Collection<String>, ldc:String("java"))
var_2_29 = invokeinterface:Iterator<String>(Collection<String>::iterator, c:Collection<String>)

while (invokeinterface:boolean(Iterator<E>::hasNext, var_2_29:Iterator<String>)) {
str = checkcast:String(java.lang.String.class, invokeinterface:String(Iterator<String>::next, var_2_29:Iterator<String>))
invokevirtual:void(PrintStream::println, getstatic:PrintStream(System::out), str:String)
}
}

从上面的反编译结果中,我们不能发现,所谓的增强 for 循环,实际上是由编译器在底层帮我们装换成了 iterator 的 while 遍历。既然调用了 iterator,那么并发修改就需要上心了,详情可以参考 java – 迭代器并发修改异常

Powered By Valine
v1.5.2