假设我有一个像这样的简单PHP循环
// Bad example
$array = array('apple','banana','cucumber');
for ($i = 1; $i < count($array); $i++) {
echo $array[$i];
}
我知道这是一种不好的做法。在循环中使用count()
更好不。
// Nice example
$array = array('apple','banana','cucumber');
$limit = count($array);
for ($i = 1; $i < $limit; $i++) {
// do something...
}
在Java中,我会这样做
// Bad example?
String[] array = {"apple","banana","cucumber"};
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
问题:这也不是一个坏习惯吗?或者它与下面的例子相同?
// Nice example?
String[] array = {"apple","banana","cucumber"};
int limit = array.length;
for(int i = 0; i < limit; i++){
System.out.println(array[i]);
}
答案 0 :(得分:6)
任何体面的编译器/解释器都应该自动优化第一个例子来匹配第二个例子(无论如何,从语义上讲,如果不完全是字面意义),可能是第三个匹配第四个例子。它被称为循环不变优化,其中编译器识别实体(变量,表达式等)在循环内不变(即不变)并将其删除循环外(松散地说)。
如果它曾经存在的话,那就完全可以了。
答案 1 :(得分:5)
您使用的“坏”示例并不等同,因此无法比较 - 即使它们表面上看起来如此。使用此说明:
for (initialization; termination; increment) {
statement(s)
}
(描述了PHP和java循环),初始化语句在循环开始时执行一次。每次迭代循环都会执行终止语句和增量。
在终止语句中使用PHP的count
是不好的原因是,对于每次迭代,都会发生count
函数调用。在您的Java示例中,array.length
不是函数调用,而是对公共成员的引用。因此,示例中使用的终止语句不是等效行为。我们期望函数调用比属性引用更昂贵。
在任何语言的for循环的终止语句中放置函数调用(或调用屏蔽函数的属性)是不好的做法描述了循环力学。这就是使PHP示例“坏”的原因,如果你在Java中使用count
- 类型的函数来循环终止语句,那也同样糟糕。那么,真正的问题是Java的Array.length
是否确实掩盖了函数调用 - 答案是“不”(参见潜在的重复问题,和/或查看http://leepoint.net/notes-java/data/arrays/arrays.html)
答案 2 :(得分:2)
主要区别在于count()
是一个函数,而array.length
是一个属性,因此与limit
变量没有区别。
答案 3 :(得分:1)
它们不一样,在Java“漂亮的例子”中,你不是每次都计算数组的长度。相反,您将其存储在limit变量中并使用它来停止计算,而不是每次迭代通过for循环调用数组上的length函数的结果。
编辑:你认为“坏习惯”的两件事都是不好的做法,“好例子”是更有效的方法(至少在理论上)。但确实在实施过程中不会有任何明显的差异。
答案 4 :(得分:1)
在java中,这并不重要,数组将此属性作为常量(public final int)。 不同之处在于java数组具有固定的大小并且不能增长,因此不需要每次都可以计算元素的访问长度。