How does “final int i” work inside of a Java for loop?

匿名 (未验证) 提交于 2019-12-03 07:50:05

问题:

I was surprised to see that the following Java code snippet compiled and ran:

for(final int i : listOfNumbers) {      System.out.println(i); }

where listOfNumbers is an array of integers.

I thought final declarations got assigned only once. Is the compiler creating an Integer object and changing what it references?

回答1:

Imagine that shorthand looks a lot like this:

for (Iterator iter = listOfNumbers.iterator(); iter.hasNext(); ) {     final int i = iter.next();     {         System.out.println(i);     } }


回答2:

See @TravisG for an explanation of the scoping rules involved. The only reason why you would use a final loop variable like this is if you needed to close over it in an anonymous inner class.

import java.util.Arrays; import java.util.List;  public class FinalLoop {     public static void main(String[] args) {         List list = Arrays.asList(new Integer[] { 0,1,2,3,4 });         Runnable[] runs = new Runnable[list.size()];          for (final int i : list) {             runs[i] = new Runnable() {                     public void run() {                         System.out.printf("Printing number %d\n", i);                     }                 };         }          for (Runnable run : runs) {             run.run();         }     } }

The loop variable is not in the scope of the Runnable when it is executed, only when it is instantiated. Without the final keyword the loop variable wouldn't be visible to the Runnable when it is eventually run. Even if it was, it would be the same value for all the Runnables.

Btw, about 10 years ago you might have seen a very small speed improvement in using final on a local variable (in some rare occasions); that hasn't been the case for a long time. Now the only reason to use final is to permit you to use a lexical closure like this.

In answer to @mafutrct:

When you write code, you do so for two audiences. The first is the computer which, as long as it is syntactically correct, will be happy with whatever choices you make. The second is for a future reader (often yourself), here the goal is to communicate the 'intent' of the code, without obscuring the 'function' of the code. Language features should be used idiomatically with as few interpretations as possible to reduce ambiguity.

In the case of the loop variable, the use of final could be used to communicate either of two things: single-assignment; or, closure. A trivial scan of the loop will tell you if the loop variable is reassigned; however, due to the interleaving of two execution paths when creating a closure, it can be easy to miss that the closure intended to capture the variable. Unless, of course, you only ever use final to indicate intent-to-capture, at which point it becomes obvious to the reader that is what is happening.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!