Java for Loop评估

时间:2010-10-07 12:34:57

标签: java loops

我想知道每次循环周期结束时是否在Java中的forwhile循环中执行条件评估。

示例:

int[] tenBig = new int[]{1,2,3,4,5,6,7,8,9,10};

for(int index = 0;index < tenBig.length;index++){
    System.out.println("Value at index: "+tenBig[index]);
}

每次循环周期结束时都会执行index < tenBig.length吗?

假设和经验告诉我是的。

我知道在这个示例中tenBig.length是常量,因此不会对性能产生影响。

但我们假设条件操作在不同情况下需要很长时间。 我知道合理的做法是将tenBig.length分配给变量。

我仍然希望每次都能评估它。

8 个答案:

答案 0 :(得分:11)

是的,它将在循环的每次迭代中逻辑地评估整个中间操作数。当JIT知道更好的情况下,当然,它可以做一些聪明的事情(甚至可能根据循环条件删除循环内的数组边界检查)。

请注意,对于JIT不了解的类型,它可能无法像这样进行特定优化 - 但仍可以内联诸如获取size()的{​​{1}}。

最后,为了便于阅读,我通常更喜欢增强的for循环:

ArrayList<T>

当然,假设您出于其他原因不需要索引。

答案 1 :(得分:6)

是。具体地,条件部分在每个循环体之前执行。所以你完全有可能永远不会进入循环体。

以你的榜样为例:

for(int index = 0;index < tenBig.lenght;index++) {
    /* ...body... */
}

这是逻辑(非文字)等价物:

int index = 0;
while (index < tenBig.length) { // happens on each loop
    /* ...body... */

    index++;
}

答案 2 :(得分:3)

是的,必须为循环的每次迭代计算表达式,以确定是保留在循环内还是继续执行程序。

请记住,你可以这样做:

for(int a = 0, z = 26; a < z; a++, z--){
    // Do some work
}

在这种情况下,表达式的两边都会发生变化,必须对每次迭代进行评估。

你是对的,如果你在for循环条件中有计算可以转移到一个单独的变量,你应该这样做:

for(int i = 0; i < ((someCount / 2) * 21.6); i++){
}

很容易:

int maxVal = (someCount / 2) * 21.6;

for(int i=0; i < maxVal; i++){
{

答案 3 :(得分:1)

如果条件表达式是循环不变并且您在JIT模式下运行,则可以执行Loop-invariant code motion之类的循环优化。

但是当在解释模式下运行时,我猜测没有太多优化要做。

答案 4 :(得分:1)

以下是几个字节码compiling examples from the JVM spec

据我所知,每次都会评估病情。

问候。

答案 5 :(得分:1)

index < tenBig.length将在每次循环周期开始之前执行。

    public static void main(String[] args) {
        int[] tenBig = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        for (int index = 0; isEvaluated() && index < tenBig.length; index++) {
            System.out.println("Value at index: " + tenBig[index]);
        }
    }

    public static boolean isEvaluated() {
        System.out.println("evaluated");
        return true;
    }

它将在循环开始之前打印"evaluated"。还有一次在循环结束之前。

答案 6 :(得分:0)

你是否问过编译器缓存了tenBig.length值,因为他知道它在循环期间不会改变?或者你问编译器是否自动知道整个表达式索引&lt;接下来的9次不需要评估tenBig.length吗?

答案 7 :(得分:0)

每次进入循环时都会执行它,包括将产生索引的最后一次评估&lt; length = false。 除此之外,即使tenBig的长度为const,循环也将始终访问此属性,因此将其分配给变量是理想的(即使它在您的示例中不是合理的速度增益)。