【问题标题】:Is Java foreach iteration order over primitives precisely defined?Java foreach 对原语的迭代顺序是否精确定义?
【发布时间】:2010-10-14 04:35:03
【问题描述】:

示例代码:

int a[] = new int[]{0, 1, 2, 3};
int result = 0;
for (int i : a)
    result += i;

循环是否保证循环遍历a[0]a[1]a[2]a[3]?我坚信答案是肯定的,但this page 似乎并没有明确说明顺序。

有可靠的参考资料吗?

【问题讨论】:

    标签: java foreach iteration


    【解决方案1】:

    根据the JLS, The enhanced for statement,你的for循环相当于

    int[] array = a;
    for (int index = 0; index < a.length; index++) {
        int i = array[index];
        result += i;
    }
    

    “其中arrayindex 是编译器生成的标识符,与增强的for 语句发生时范围内的任何其他标识符(编译器生成或其他)不同。” (这里稍微解释一下变量名)。

    所以是的:订单绝对有保证。

    【讨论】:

      【解决方案2】:

      section 14.14.2 of the Java Language Specification, 3rd edition

      如果表达式的类型是子类型 的 Iterable,然后让我成为 表达式 Expression.iterator()。 增强的 for 语句是 相当于一个基本的for语句 形式:

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

      #i 是编译器生成的 不同于任何标识符的标识符 其他标识符(编译器生成的 或其他)在范围内(§6.3) 在增强的点 语句发生。

      【讨论】:

        【解决方案3】:

        它在JLS 中声明:

        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
        }
        

        【讨论】:

        【解决方案4】:

        我在您引用的页面中没有发现任何暗示无序迭代的内容。能发一下具体的报价吗?

        无论如何,我发现这段代码:

        public static void main( String args[] ) {
            double a[] = new double[] { 0, 1, 2, 3 };
            int result = 0;
            for ( double i : a ) {
                result += i;
            }
        

        反编译成旧式循环:

         public static void main(String args[])
            {
                double a[] = {
                    0.0D, 1.0D, 2D, 3D
                };
                int result = 0;
                double ad[];
                int k = (ad = a).length;
                for(int j = 0; j < k; j++)
                {
                    double i = ad[j];
                    result = (int)((double)result + i);
                }
            }
        

        当然,这与保证不同,但至少对数组的无序迭代会非常奇怪,并且似乎违背了明显的常识实现。

        【讨论】:

        • 拆分元素和线程循环可能会更快。一些编译器已经展开和矢量化循环进行数学运算。那是不正常的。线程可能是下一件事。
        猜你喜欢
        • 1970-01-01
        • 2012-03-15
        • 2012-09-17
        • 2010-12-25
        • 2014-02-07
        • 2023-04-06
        • 2021-05-27
        • 1970-01-01
        相关资源
        最近更新 更多