这是一个好问题,我很乐意看到一些深入的答案。但是,官方文件说:
设计师们知道这些缺点,他们有意识地决定采用干净,简单的结构,可以覆盖绝大多数情况。
绝大多数情况对我来说就是答案。
顺便说一句,就个人而言,我认为Java中的循环只是标准迭代器循环的一个很好的语法。因此,编译器为结构创建迭代器,并使用变量获取当前迭代的值。为了确保变量已经初始化,你需要为循环范围声明它(我认为这可以防止变量在其他地方使用,例如在另一个线程中)。因此,不能在循环后使用变量。但是,这只是我的观点,我很乐意听到更了解它的人的意见。:)foreach
编辑这是一篇关于Java中循环的有趣文章。foreach
另一个编辑我分析了(使用jclasslib)这些方法的字节码:
private static void testForEach(ArrayList<String> als) {
for(String s: als)
System.out.println(s);
}
private static void testIterator(ArrayList<String> als) {
for(Iterator<String> is = als.iterator(); is.hasNext();) {
String s = is.next();
System.out.println(s);
}
}
这两种方法由相同的字节码表示:
0 aload_0
1 invokevirtual #2 <java/util/ArrayList.iterator>
4 astore_1
5 aload_1
6 invokeinterface #3 <java/util/Iterator.hasNext> count 1
11 ifeq 34 (+23)
14 aload_1
15 invokeinterface #4 <java/util/Iterator.next> count 1
20 checkcast #5 <java/lang/String>
23 astore_2
24 getstatic #6 <java/lang/System.out>
27 aload_2
28 invokevirtual #7 <java/io/PrintStream.println>
31 goto 5 (-26)
34 return
区别在于第 1 行,后一种方法使用 。但是,这两个调用都会导致调用 相同的方法 。因此,正如文档所说,这似乎只不过是编译器转换为预定义结构的语法糖。这并没有回答为什么会这样。虽然这很有趣,但在讨论的背景下可能值得一提。invokevirtual #8
Iterator
foreach