每个循环的通常形式是:
for(Foo bar: bars){
bar.doThings();
}
但是如果我想在循环之后保留bar,我可以不使用for循环:
Foo bar = null;
// - Syntax error on token "bar", Identifier expected after this token
for(bar: bars){
if(bar.condition())
break;
}
bar.doThings();
for循环得到上面提到的语法错误。
为什么会这样? 我对解决方法不感兴趣,但只是对此限制背后的考虑因素感到好奇。
相反,对于普通的for循环,变量可以在外部声明或根本不声明......
int i = 1;
for(;i<max;i++){
for(;;){
// Do things
}
}
答案 0 :(得分:29)
这是一个很好的问题,我很乐意看到一些深入的答案。但是,official documentation说:
这些缺点是众所周知的 有意识的设计师 决定干净,简单 构建将覆盖伟大的 大多数情况。
绝大多数案件都是我的答案。
另外,就个人而言,我认为Java中的foreach
循环只是标准迭代器循环的一个很好的语法。因此,编译器为结构创建迭代器,并使用该变量获取当前迭代的值。为了确保变量已经初始化,你需要为循环范围声明它(我认为这可以防止变量在其他地方使用,例如在另一个线程中)。因此,您不能在循环后使用该变量。但是,这只是我的观点,我很乐意听到更了解它的人的消息。 :)
编辑以下是关于Java中foreach
循环的an interesting article。
另一个编辑我分析了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
似乎只是编译器转换为预定义构造的语法糖,就像文档所说的那样。这并没有回答为什么它是的问题。我认为这很有趣,在讨论的背景下可能值得一提。
答案 1 :(得分:4)
我猜他们只想宣传“良好做法”:来自Java language guide:
设计师知道这些缺点,他们有意识地决定采用干净,简单的结构来覆盖绝大多数情况。
正如我们所知,你可以通过将for-each循环扩展为基于旧迭代器的样式来模拟你要求的行为,并且可能他们只是认为它足够好。
答案 2 :(得分:3)
在这种情况下迭代列表的方法是:
Foo bar = null;
for(Iterator<Foo> barIterator = bars.iterator(); barIterator.hasNext();){
bar = barIterator.next(); // or whatever else you want to do
...
}
除非列表实现RandomAccess!
,否则不要使用索引迭代列表增强的for循环只是这个迭代器方法的语法糖,它将变量(此处为bar)保持在循环的本地。 (通常,将变量保持为局部变量是一件好事。)
答案 3 :(得分:1)
这种新语法的目的是为了美化,因为它并没有真正为Java添加任何新东西。我的猜测是他们不允许你所做的语法的唯一原因是:它不漂亮! :)