Java是如何由编译器生成的循环代码

Nik*_*arg 18 java foreach

Java是如何由编译器生成的循环代码?

例如,如果我有:

for(String s : getStringArray() )
{
   //do something with s
}
Run Code Online (Sandbox Code Playgroud)

where getStringArray()函数返回我想要循环的数组,函数会一直调用还是只调用一次?一般来说,使用这个结构循环的代码有多优?

pol*_*nts 56

关于增强for循环的语义

以下是Java语言规范第3版的相关摘录,为了清晰起见,略有编辑:

JLS 14.14.2增强的for声明

增强的for声明具有以下形式:

for ( Type Identifier : Expression ) Statement
Run Code Online (Sandbox Code Playgroud)

如果类型Expression是数组类型,T[]则增强for语句的含义由以下基本for语句给出:

T[] a = Expression;
for (int i = 0; i < a.length; i++) {
    Type Identifier = a[i];
    Statement
}
Run Code Online (Sandbox Code Playgroud)

其中ai是编译器生成的标识符,它们与for发生增强语句的范围内的任何其他标识符(编译器生成的或其他标识符)不同.

所以实际上语言确实 Expression 只会被评估一次.

为了完整性,这Expression是类型的等价Iterable:

JLS 14.14.2增强的for声明

增强的for声明具有以下形式:

for ( Type Identifier : Expression ) Statement
Run Code Online (Sandbox Code Playgroud)

如果类型Expression是子类型Iterable,那么让它I成为表达式的类型Expression.iterator().增强for语句等同于for表单的基本语句:

for (I iter = Expression.iterator(); iter.hasNext(); ) {
    Type Identifier = iter.next();
    Statement
}
Run Code Online (Sandbox Code Playgroud)

其中iter是编译器生成的标识符,它与for发生增强语句的范围内的任何其他标识符(编译器生成的或其他标识符)不同.

请注意,如果Expression既不是Iterable数组也不是数组,那么它是编译时错误,所以上面两个是唯一可以使用增强for循环的情况.此外,为清楚起见,上述引号遗漏了关于for环上附着的任何标签的信息以及附在其上的任何修饰符Identifier,但这些都按照人们的预期处理.


关于增强for循环的性能

以下是Effective Java 2nd Edition的引用,第46项:首选每个循环到传统for循环

在1.5版中引入的for-each循环通过完全隐藏迭代器或索引变量来消除混乱和错误的机会.由此产生的习语同样适用于集合和数组.请注意,即使对于数组,使用for-each循环也不会有性能损失.事实上,for在某些情况下,它可能比普通循环提供轻微的性能优势,因为它只计算一次数组索引的限制.虽然您可以手动执行此操作,但程序员并不总是这样做.

因此,本书声称实际上一些编译器超越了JLS转换并对for-each循环执行了额外的优化(当然,仍然保持其语义).

总之,您不必担心for-each循环的性能.语言规范是合理的(Expression仅评估一次),正是因为这是许多场景中的首选构造,编译器将确保尽可能地优化它们.

也可以看看


fas*_*ava -1

编译器可能只调用它一次,但您可以依赖它。这可能不是一个好的编码实践。如果getStringArray()每次返回相同的数组,为什么不先设置为一个变量呢?

编辑- 答案随着收到的评论而改变。

  • 事实上,您*可以*依赖于它被调用一次。请参阅http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.14.2 (4认同)
  • 我认为在合理的范围内调用“Expression”中的方法是可以的。`for (char c : str.toCharArray())`、`for (MyEnum e : MyEnum.values())` 等似乎是惯用的。 (2认同)