我想知道每次循环周期结束时是否在Java中的for
和while
循环中执行条件评估。
示例:
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
分配给变量。
我仍然希望每次都能评估它。
答案 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)
答案 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,循环也将始终访问此属性,因此将其分配给变量是理想的(即使它在您的示例中不是合理的速度增益)。