Java的for循环代码是如何由编译器生成的 [英] How is Java's for loop code generated by the compiler

查看:132
本文介绍了Java的for循环代码是如何由编译器生成的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,如果我有:

<$>

如何编译生成的Java循环代码?对于(String s:getStringArray())
{
//用s
做某事}

其中 getStringArray()是一个返回我想循环的数组的函数,被称为总是或只有一次?如何优化循环使用这个结构的代码呢?

loop

以下是为简明起见而对 Java语言规范第三版 p>


JLS 14.14.2针对语句的增强型



增强 for 语句的格式为:

  for(类型标识符:表达式)语句

如果 Expression 的类型是一个数组类型 T [] ,那么对于语句增强的的含义由下面的基本 for 语句:

  T [] a =表达式; 
for(int i = 0; i< a.length; i ++){
Type Identifier = a [i];


$ / code $ / pre

其中 a i 是编译器生成的标识符,它与任何其他标识符(编译器生成的或其他标识符)因此,实际上,该语言确实保证了 for
语句


$ / / em> 表达式 只会计算一次。 为了完整性,这里是当表达式类型为 Iterable


JLS 14.14.2对于语句增强的



c>语句的格式如下:
$ b $ pre $ for(类型标识符:表达式)语句

如果 Express的类型ion Iterable 的子类型,那么让 I 为表达式的类型 Expression.iterator()。对于语句增强的相当于以下形式的语句的基本

  for(I iter = Expression.iterator(); iter.hasNext();){
类型标识符= iter.next();


$ / code $ / pre
$ b $ iter 是一个编译器生成的标识符,它与在增强的 for 语句发生时位于范围内的任何其他标识符(编译器生成的或其他的) 。

请注意,如果 Expression 既不是编译时错误一个 Iterable 也不是一个数组,所以上面两个是唯一可以使用增强的 for 循环的情况。此外,为了清楚起见,上面的引用省略了有关循环中附加的任何标签的信息以及附加在标识符,但这些都按照预期的方式处理。




在增强的 loop



以下是有效的Java第2版,第46项:每个循环优先于循环


在版本1.5中引入的for-each循环通过隐藏迭代器或索引来摆脱混乱和错误的机会完全可变。最终的习惯用法同样适用于集合和数组。请注意,使用for-each循环对于数组没有性能损失,甚至对于数组也是如此。事实上,在某些情况下,它可能比普通的循环提供轻微的性能优势,因为它只计算一次数组索引的限制。虽然您可以手动完成这项工作,但程序员并不总是这样做。


因此,本书声称事实上,有些编译器超越了JLS的翻译,并在for-each循环上执行了额外的优化(当然,当然仍然保持其语义)。

总之,不要担心for-each循环的性能。由于语言的规范是明智的( Expression只能被评估一次),而正是因为这是许多场景中的首选构造,所以编译器会确保

参见




  • Java语言指南/ for-each循环


    • 有习惯用法的例子,以及它如何帮助最大限度地减少错误的机会
    • >

    How is Java's for loop code generated by the compiler?

    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?

    解决方案

    On the semantics of enhanced for loop

    Here is the relevant excerpts from the Java Language Specification 3rd Edition, slightly edited for clarity:

    JLS 14.14.2 The enhanced for statement

    The enhanced for statement has the form:

    for ( Type Identifier : Expression ) Statement
    

    If the type of Expression is an array type, T[], then the meaning of the enhanced for statement is given by the following basic for statement:

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

    where a and i are compiler-generated identifiers that are distinct from any other identifiers (compiler-generated or otherwise) that are in scope at the point where the enhanced for statement occurs.

    So in fact the language does guarantee that Expression will only be evaluated once.

    For completeness, here's the equivalence when the Expression is of type Iterable:

    JLS 14.14.2 The enhanced for statement

    The enhanced for statement has the form:

    for ( Type Identifier : Expression ) Statement
    

    If the type of Expression is a subtype of Iterable, then let I be the type of the expression Expression.iterator(). The enhanced for statement is equivalent to a basic for statement of the form:

    for (I iter = Expression.iterator(); iter.hasNext(); ) {
        Type Identifier = iter.next();
        Statement
    }
    

    where iter is a compiler-generated identifier that is distinct from any other identifiers (compiler-generated or otherwise) that are in scope at the point where the enhanced for statement occurs.

    Note that it is a compile-time error if Expression is neither an Iterable nor an array, so the above two are the only cases where you can use an enhanced for loop. Also, for clarity, the above quotes leave out information regarding any labels attached on the for loop and any modifiers attached on the Identifier, but these are handled as one would expect.


    On the performance of enhanced for loop

    Here's a quote from Effective Java 2nd Edition, Item 46: Prefer for-each loops to traditional for loops

    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 for loop in some circumstances, as it computes the limit of the array index only once. While you can do this by hand, programmers don't always do so.

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

    In summary, you should not worry about the performance of for-each loop. The specification by the language is sensible (Expression only evaluated once), and precisely because this is the preferred construct in many scenarios, compilers will make sure to optimize them as best they can.

    See also

    这篇关于Java的for循环代码是如何由编译器生成的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆