这两个循环之间有什么区别吗?

ham*_*mid 6 java performance loops

以下两个代码片段之间在性能方面有什么不同吗?

for(String project : auth.getProjects()) {
    // Do something with 'project'
}
Run Code Online (Sandbox Code Playgroud)

String[] projects = auth.getProjects();
for(String project : projects) {
    // Do something with 'project'
}
Run Code Online (Sandbox Code Playgroud)

对我来说,我认为第二个更好,但它更长.第一个更短,但我不确定它是否更快.我不确定,但对我而言,似乎每次循环都被迭代,auth.getProjects被调用.那不是这样吗?

ug_*_*ug_ 10

编辑:@StephenC是对的,JLS是一个更好的地方,可以找到这种性质的答案.这是语言规范中增强的for循环链接.在那里,你会发现它生成了几种不同类型的for语句,但是它们都不会多次调用该方法.


简单测试表明该方法只调用一次

public class TestA {
    public String [] theStrings;

    public TestA() {
        theStrings = new String[] {"one","two", "three"};
        for(String string : getTheStrings()) {
            System.out.println(string);
        }
    }

    public String[] getTheStrings() {
        System.out.println("get the strings");
        return theStrings;
    }

    public static void main(String [] args) {
        new TestA();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

get the strings
one
two
three
Run Code Online (Sandbox Code Playgroud)

所以基本上他们是一回事.唯一可能对第二个有益的是,如果你想在for循环之外使用数组.


编辑

你让我很好奇java编译器如何处理这个,所以使用上面的代码我反编译了类文件,并且结果是什么

public class TestA
{

    public TestA()
    {
        String as[];
        int j = (as = getTheStrings()).length;
        for(int i = 0; i < j; i++)
        {
            String string = as[i];
            System.out.println(string);
        }

    }

    public String[] getTheStrings()
    {
        System.out.println("get the strings");
        return theStrings;
    }

    public static void main(String args[])
    {
        new TestA();
    }

    public String theStrings[] = {
        "one", "two", "three"
    };
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,编译器只需将for循环重构为标准循环!它还进一步证明,在编译器完成它之后它们实际上是完全相同的.

  • *"简单的测试表明该方法只被调用一次"* - 简单的测试可能会产生误导......'因为你不知道你应该测试什么.更好的方法是阅读JLS. (3认同)