java for循环定义变量,为什么在java中的for-each循环中需要声明变量

The usual form the of for each loop is this:

for(Foo bar: bars){

bar.doThings();

}

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

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.

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

int i = 1;

for(;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.

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. :)

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

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

private static void testForEach(ArrayList als) {

for(String s: als)

System.out.println(s);

}

private static void testIterator(ArrayList als) {

for(Iterator 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

4 astore_1

5 aload_1

6 invokeinterface #3 count 1

11 ifeq 34 (+23)

14 aload_1

15 invokeinterface #4 count 1

20 checkcast #5

23 astore_2

24 getstatic #6

27 aload_2

28 invokevirtual #7

31 goto 5 (-26)

34 return

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值