Why is declaration of the variable required inside a for-each loop in java

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<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

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.

Leave a Comment