java Java的for循环代码是如何由编译器生成的
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3433282/
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 is Java's for loop code generated by the compiler
提问by Nikhil Garg
How is Java's for loop code generated by the compiler?
Java 的 for 循环代码是如何由编译器生成的?
For example, if I have:
例如,如果我有:
for(String s : getStringArray() )
{
//do something with s
}
where getStringArray()is a function that returns the Array I want to loop on, would function be called always or only once? How optimal is the code for looping using this construct in general?
getStringArray()返回我想要循环的数组的函数在哪里,是始终调用函数还是仅调用一次函数?一般而言,使用此构造的循环代码的优化程度如何?
回答by polygenelubricants
On the semantics of enhanced forloop
论增强for循环的语义
Here is the relevant excerpts from the Java Language Specification 3rd Edition, slightly edited for clarity:
以下是Java Language Specification 3rd Edition的相关摘录,为清晰起见,略作编辑:
JLS 14.14.2 The enhanced
forstatementThe enhanced
forstatement has the form:for ( Type Identifier : Expression ) StatementIf the type of
Expressionis an array type,T[], then the meaning of the enhancedforstatement is given by the following basicforstatement:T[] a = Expression; for (int i = 0; i < a.length; i++) { Type Identifier = a[i]; Statement }where
aandiare compiler-generated identifiers that are distinct from any other identifiers (compiler-generated or otherwise) that are in scope at the point where the enhancedforstatement occurs.
JLS 14.14.2 增强
for语句增强
for语句具有以下形式:for ( Type Identifier : Expression ) Statement如果的类型
Expression是数组类型,T[]则增强for语句的含义由以下基本for语句给出:T[] a = Expression; for (int i = 0; i < a.length; i++) { Type Identifier = a[i]; Statement }其中
a和i是编译器生成的标识符,它们不同于在增强for语句出现点的范围内的任何其他标识符(编译器生成的或其他方式)。
So in fact the language does guarantee thatExpressionwill only be evaluated once.
所以事实上该语言确实保证Expression只会被评估一次。
For completeness, here's the equivalence when the Expressionis of type Iterable:
为完整起见,当Expressionis 为 type时,这里是等价的Iterable:
JLS 14.14.2 The enhanced
forstatementThe enhanced
forstatement has the form:for ( Type Identifier : Expression ) StatementIf the type of
Expressionis a subtype ofIterable, then letIbe the type of the expressionExpression.iterator(). The enhancedforstatement is equivalent to a basicforstatement of the form:for (I iter = Expression.iterator(); iter.hasNext(); ) { Type Identifier = iter.next(); Statement }where
iteris a compiler-generated identifier that is distinct from any other identifiers (compiler-generated or otherwise) that are in scope at the point where the enhancedforstatement occurs.
JLS 14.14.2 增强
for语句增强
for语句具有以下形式:for ( Type Identifier : Expression ) Statement如果 的类型
Expression是 的子类型Iterable,则 letI是表达式的类型Expression.iterator()。增强for语句等效于for以下形式的基本语句:for (I iter = Expression.iterator(); iter.hasNext(); ) { Type Identifier = iter.next(); Statement }其中
iter是编译器生成的标识符,它与增强for语句发生点范围内的任何其他标识符(编译器生成的或其他方式的)不同。
Note that it is a compile-time error if Expressionis neither an Iterablenor an array, so the above two are the only cases where you can use an enhanced forloop. Also, for clarity, the above quotes leave out information regarding any labels attached on the forloop and any modifiers attached on the Identifier, but these are handled as one would expect.
请注意,如果Expression既不是 anIterable也不是数组,则这是编译时错误,因此上述两种情况是您可以使用增强for循环的唯一情况。此外,为了清楚起见,上面的引用省略了有关for循环上附加的任何标签和 上附加的任何修饰符的信息Identifier,但这些都按预期进行处理。
On the performance of enhanced forloop
关于增强for循环的性能
Here's a quote from Effective Java 2nd Edition, Item 46: Prefer for-each loops to traditional for loops
这是Effective Java 2nd Edition, Item 46的引述:Prefer for-each 循环而不是传统的 for 循环
The for-each loop, introduced in release 1.5, gets rid of the clutter and the opportunity for error by hiding the iterator or index variable completely. The resulting idiom applies equally to collections and arrays. Note that there is no performance penalty for using the for-each loop, even for arrays. In fact, it may offer a slight performance advantage over an ordinary
forloop in some circumstances, as it computes the limit of the array index only once. While you cando this by hand, programmers don't always do so.
1.5 版中引入的 for-each 循环通过完全隐藏迭代器或索引变量来消除混乱和出错的机会。由此产生的习语同样适用于集合和数组。请注意,使用 for-each 循环没有性能损失,即使对于数组也是如此。事实上,
for在某些情况下,它可能比普通循环提供轻微的性能优势,因为它只计算一次数组索引的限制。虽然您可以手动完成此操作,但程序员并不总是这样做。
Thus the book claims that in fact some compilers go beyond the JLS translation and performs additional optimization on the for-each loop (while still maintaining its semantics, of course).
因此,这本书声称实际上一些编译器超越了 JLS 翻译,并对 for-each 循环执行了额外的优化(当然,同时仍然保持其语义)。
In summary, you should not worry about the performance of for-each loop. The specification by the language is sensible (Expressiononly evaluated once), and precisely because this is the preferred construct in many scenarios, compilers will make sure to optimize them as best they can.
总之,您不必担心 for-each 循环的性能。语言的规范是合理的(Expression只评估一次),正是因为这是许多场景中的首选构造,编译器将确保尽其所能优化它们。
See also
也可以看看
- Java Language Guide/The for-each loop
- Has examples of idiomatic usage and how it can help minimize chances of errors
- Java 语言指南/for-each 循环
- 有惯用用法的例子以及它如何帮助最大限度地减少错误的机会
回答by Guillaume Holler
JDK 1.4 introduced the RandomAccessinterface. It is meant to give a hint to algorithms when, for a given Listimplementation, it is more efficient to iterate through:
JDK 1.4 引入了该RandomAccess接口。它旨在为算法提供提示,对于给定的List实现,迭代执行以下操作更有效:
for (int i = 0, n = list.size(); i < n; i++) {
list.get(i);
}
than
比
for (Iterator i = list.iterator(); i.hasNext(); ) {
i.next();
}
Does the foreach loop take this into account? Or does it completely ignore the fact that a given Iterable is in fact a List?
foreach 循环是否考虑到了这一点?或者它是否完全忽略了一个事实,即给定的 Iterable 实际上是一个 List?
It should be noted that this would imply that adding a (iterable instanceof List && iterable instanceof RandomAccess)test and a downcast to Listwould work, which would add an overhead that's not always worth it and could be considered a premature optimization for a compiler syntactic sugarfeature.
应该注意的是,这意味着添加一个(iterable instanceof List && iterable instanceof RandomAccess)测试和向下转换 toList会起作用,这会增加并不总是值得的开销,并且可能被认为是对编译器语法糖功能的过早优化。
回答by fastcodejava
Compiler might call it just once, but you candepend on it. It may not be a good coding practice.
If getStringArray()returns same array each time, why not set to a variable first?
编译器可能只调用一次,但您可以依赖它。这可能不是一个好的编码习惯。如果getStringArray()每次都返回相同的数组,为什么不先设置一个变量呢?
EDIT- answer changed with the comments received.
编辑- 答案随着收到的评论而改变。
回答by borris
for loop is same like loop in javascript so no need to afraid
for 循环与 javascript 中的循环相同,因此无需担心
example:
例子:
for(int i=0;i<10;i++)
{
System.out.Println(i);
}

