为什么在java中的for-each循环中需要声明变量 [英] Why is declaration of the variable required inside a for-each loop in java

查看:540
本文介绍了为什么在java中的for-each循环中需要声明变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每个循环的通常形式是:

The usual form the of for each loop is this:

for(Foo bar: bars){
    bar.doThings();
}

但是如果我想在循环之后保留bar,我可以使用for each循环:

But if I want to retain bar until after the loop, I can not use the for each loop:

Foo bar = null;
// - Syntax error on token "bar", Identifier expected after this token
for(bar: bars){ 
    if(bar.condition())
        break;
}
bar.doThings();

for循环得到上面提到的语法错误。

The for loop gets the syntax error mentioned above.

为什么会这样?
我对解决方法不感兴趣,但只是对此限制背后的考虑因素感到好奇。

Why is this? I'm not interested in workarounds, but just curious to the considerations behind this limitation.

相比之下,对于普通的for循环,变量可以在外部声明或根本不声明...

In contrast, with an ordinary for loop, the variable can be declared outside or not at all...

int i = 1;
for(;i<max;i++){
    for(;;){
        // Do things
    }
}


推荐答案

这是一个很好的问题,我很乐意看到一些深入的答案。但是,官方文档说:

This is a good question and I would be happy to see some in-depth answer. However, the official documentation says:



设计师知道这些缺点,他们做出了一个有意识的
决定采用干净简单的
构造可以覆盖大部分
的大部分案例。

These shortcomings were known by the designers, who made a conscious decision to go with a clean, simple construct that would cover the great majority of cases.

绝大多数案例都是我的答案。

The great majority of cases is the answer for me.

总的来说,就个人而言,我认为Java中的 foreach 循环只是标准的一个很好的语法迭代器循环。因此,编译器为结构创建迭代器,并使用该变量获取当前迭代的值。为了确保变量已经初始化,你需要为循环范围声明它(我认为这可以防止变量在其他地方使用,例如在另一个线程中)。因此,您不能在循环后使用该变量。但是,这只是我的意见,我很乐意听到更了解它的人的意见。 :)

On a side note, personally, I think that foreach loop in Java is just a nice syntax for a standard iterator loop. So, the compiler creates the iterator for the structure and uses the variable to get the value for current iteration. To ensure that the variable has been initialised you need to declare it for the scope of loop (and I think this prevents the variable from being used somewhere else, e.g. in another thread). Because of that, you cannot use the variable after the loop. But, this is just my opinion and I would be very happy to hear from someone who knows it better. :)

编辑这是一篇有趣的文章关于Java中的 foreach 循环。

Edit Here is an interesting article about foreach loops in Java.

我分析了另一个编辑 jclasslib 这些方法的字节码:

Another edit I analysed (with jclasslib the bytecode of these methods:

 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);
  } 
 }

两种方法都有代表通过相同的字节码:

Both methods are represented by the same bytecode:

 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 只不过是编译器只是转换为预定义构造的语法糖,就像文档所说的那样。这并没有回答为什么它是的问题。我觉得这很有意思,在讨论的背景下可能值得一提。

The difference is in line 1, the latter method uses invokevirtual #8. However, both invocations result in calling the same method of Iterator. So, it seems that foreach is nothing more than a syntactic sugar that the compiler just translates into a predefined construct, just as the documentation says. This does not answer the question why it is the way it is. I though this is just interesting and might be worth to know, in the context of the discussion.

这篇关于为什么在java中的for-each循环中需要声明变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆