【问题标题】:Does Java's for-each call an embedded method (that returns the collection) for every iteration?Java 的 for-each 是否为每次迭代调用一个嵌入式方法(返回集合)?
【发布时间】:2011-03-18 21:53:58
【问题描述】:

如果有一个方法调用 MyClass.returnArray() 并且我使用 for-each 构造(也称为“增强型 for”循环)遍历数组:

for (ArrayElement e : MyClass.returnArray()) {
   //do something
}

那么每次迭代都会调用returnArray() 方法吗?

【问题讨论】:

    标签: java foreach


    【解决方案1】:

    不,不会。第一次调用的结果将存储在编译后的代码中的一个临时变量中。

    来自Effective Java 2nd. Ed.,第 46 条:

    请注意,使用没有性能损失 for-each 循环,即使对于数组也是如此。事实上,它可能会提供轻微的性能优势 在某些情况下,通过普通的 for 循环,因为它计算了 数组索引只有一次。

    【讨论】:

    • 如果您想知道否决票,我同意这个结论,但我认为您引用的部分并不能很好地解释原因。主要讲的是数组索引,这个没有问题,也无法解释——更不用说证明——“表达式”中的returnArray方法只被调用了一次。
    【解决方案2】:

    来自java language spec

    EnhancedForStatement:
        for ( VariableModifiersopt Type Identifier: Expression) Statement
    

    及以后:

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

    这(在伪代码中)相当于用于数组的高级 for 循环。并且很清楚,Expression 被评估一次,结果数组被分配给T[] a

    因此,即使在高级 for 循环语句中使用复杂的表达式也是完全安全的。

    【讨论】:

      【解决方案3】:

      没有。

      for 循环只是语法糖。它的行为 differently 取决于它是否应用于 Array 参数或实现 Iterable 接口的对象。

      对于 Iterable 对象,循环扩展为如下内容:

      Iterator<ArrayElement> iter = iterableObject.iterator();
      while (iter.hasNext()) {
         ArrayElement e = iter.next();
         // do smth
      }
      

      您的示例代码实际上是这样的:

      Object[] temp = Method.returnArray();
      for ( int i = 0; i < temp.length; i++ ) {
        ArrayElement e = (ArrayElement) temp[i];
        // do smth
      }     
      

      【讨论】:

      • 这对于Iterable 的所有子类都是完全正确的,但高级 for 循环也可以与数组一起使用,我想这就是问题的重点。它仍然是“语法糖”,但有点不同。
      【解决方案4】:

      不,它会被调用一次。它不像标准 for 循环的终止条件,它在每次迭代时都会被评估。

      【讨论】:

        猜你喜欢
        • 2010-10-04
        • 2018-10-25
        • 1970-01-01
        • 1970-01-01
        • 2021-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-25
        相关资源
        最近更新 更多