2010-10-07 79 views
6

我想知道每当循环结束时,是否在Java环境中使用forwhile循环执行条件评估。Java for循环评估

例子:

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分配给一个变量。

我仍然想确保每次评估它。

+1

我知道这是在c + +的情况。但对于Java来说呢? – Koekiebox 2010-10-07 12:35:38

+0

在你的例子中,for的中间部分将被评估11次。一旦你修正了'length'的拼写,以便它实际编译,那就是。 – Powerlord 2010-10-07 14:04:43

回答

9

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

请注意,对于JIT不知道的类型,它可能无法像这样特别优化 - 但可能仍然内联诸如获取ArrayList<T>size()之类的内容。

最后,我一般喜欢增强的for循环的可读性:

for (int value : tenBig) { 
    ... 
} 

当然,这是假设你不需要其他原因的指标。

+1

增强型for循环有一个值得注意的改进:根据JLS,表达式(在您的情况下为'tenBig')仅评估一次。 – 2010-10-07 12:44:14

+0

我不喜欢“增强”循环的唯一情况是它不检查空值。换句话说,如果tenBig对象为null,则会引发NullPointerException,这是有道理的,但如果事先检查对象为null,它将会非常棒。 – Koekiebox 2010-10-08 09:27:19

+5

@Koekiebox:你认为在这种情况下应该怎么做?把它当作一个空的集合?就我个人而言,我认为NPE在这里是正确的结果。 – 2010-10-08 09:30:43

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++){ 
{ 
0

您是否问过编译器缓存tenBig.length值,因为他知道它在循环过程中不会改变?或者你问问编译器是否自动知道整个表达式索引< tenBig.length不需要在接下来的9次中进行评估?

6

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

所以,把你的例子:

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

这是合乎逻辑的(不是字面)相当于:

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

    index++; 
} 
0

这将执行每次循环进入,包括最后评价这将产量指数<长度=假。 除此之外,即使tenBig的长度为常量,循环将始终访问此属性,因此将它分配给变量(即使它不是您的示例中合理的速度增益)是理想选择。

1

如果条件表达式是循环不变量并且您正在JIT模式下运行,则可以完成循环优化,如Loop-invariant code motion

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

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"。还有一次在循环结束之前。