为什么在Java的for-each循环中需要声明变量

|| 每个循环的通常形式是:
for(Foo bar: bars){
    bar.doThings();
}
但是,如果我想在循环之后一直保留bar,则不能为每个循环使用:
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
    }
}
    
已邀请:
这是一个很好的问题,我很乐意看到一些深入的答案。但是,官方文档说:   这些缺点是众所周知的   有意识的设计师   决定采用干净,简单的方法   可以覆盖伟大的结构   大多数情况下。 绝大多数情况是我的答案。 顺便说一句,就我个人而言,我认为Java中的“ 3”循环对于标准的迭代器循环而言只是一种不错的语法。因此,编译器为结构创建迭代器,并使用变量获取当前迭代的值。为了确保变量已初始化,您需要在循环范围内声明它(我认为这可以防止变量在其他地方使用,例如在另一个线程中使用)。因此,您不能在循环后使用变量。但是,这只是我的观点,如果能更好地了解它,我将非常高兴。 :) 编辑这里是有关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
。因此,似乎“ 3”不过是一种语法糖,编译器只是将其翻译为预定义的结构,正如文档所述。这不能回答为什么是这样的问题。在讨论的背景下,我虽然很有趣,但也许值得一读。     
我猜他们只是想推广“良好做法”:来自Java语言指南:   这些缺点为设计师所知,他们明智地决定采用一种干净,简单的结构来覆盖绝大多数案例。 众所周知,您可以通过将for-each循环扩展到基于迭代器的旧样式来模拟您所要求的行为,并且可能他们只是认为它足够好。     
在这种情况下,迭代列表的方法是:
Foo bar = null;
for(Iterator<Foo> barIterator = bars.iterator(); barIterator.hasNext();){ 
   bar = barIterator.next(); // or whatever else you want to do
   ...
}
除非列表实现RandomAccess,否则请勿使用索引遍历列表! 增强的for循环只是此迭代器方法的语法糖,它使变量(此处为bar)保持局部于循环中。 (通常,使变量尽可能局部化是一件好事。)     
这种新语法的目的是美化,因为它实际上并没有为Java添加任何新内容。我的猜测是,他们出于唯一原因不允许使用您的语法:它不漂亮! :)     

要回复问题请先登录注册