“final int i”如何在 Java for 循环中工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3911167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does "final int i" work inside of a Java for loop?
提问by Abe
I was surprised to see that the following Java code snippet compiled and ran:
我很惊讶地看到以下 Java 代码片段编译并运行:
for(final int i : listOfNumbers) {
System.out.println(i);
}
where listOfNumbers is an array of integers.
其中 listOfNumbers 是一个整数数组。
I thought final declarations got assigned only once. Is the compiler creating an Integer object and changing what it references?
我认为最终声明只分配了一次。编译器是否创建了一个 Integer 对象并更改了它引用的内容?
回答by Travis Gockel
Imagine that shorthand looks a lot like this:
想象一下,速记看起来很像这样:
for (Iterator<Integer> iter = listOfNumbers.iterator(); iter.hasNext(); )
{
final int i = iter.next();
{
System.out.println(i);
}
}
回答by Recurse
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.
有关所涉及的范围规则的解释,请参阅 @TravisG。使用这样的最终循环变量的唯一原因是,如果您需要在匿名内部类中关闭它。
import java.util.Arrays;
import java.util.List;
public class FinalLoop {
public static void main(String[] args) {
List<Integer> 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.
循环变量在执行的时候不在Runnable的作用域内,只有在实例化的时候才在。如果没有final
关键字,当 Runnable 最终运行时,循环变量将不可见。即使是这样,所有 Runnable 的值也将相同。
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.
顺便说一句,大约 10 年前,您可能已经看到在局部变量上使用 final 的速度提升非常小(在极少数情况下);很久没有这样了。现在使用 final 的唯一原因是允许您使用这样的词法闭包。
In answer to @mafutrct:
回答@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.
在循环变量的情况下,final 的使用可用于传达以下两种情况之一:单赋值;或者,关闭。对循环的简单扫描将告诉您循环变量是否被重新分配;然而,由于创建闭包时两条执行路径的交错,很容易错过闭包旨在捕获变量。当然,除非你只使用 final 来表示意图捕获,在这一点上,读者很清楚正在发生的事情。