Java For循环差异
在Java中,这些语句在内存占用和效率方面是否完全相同?Java For循环差异,java,loops,for-loop,foreach,Java,Loops,For Loop,Foreach,在Java中,这些语句在内存占用和效率方面是否完全相同? 首先: Object[] array = new Object[100]; int i = 0; for (; i < array.length; i++){ Object o = array[i]; //do something } Object[] array = new Object[100]; for (int i = 0; i < array.length; i++){ Object o = a
首先:
Object[] array = new Object[100];
int i = 0;
for (; i < array.length; i++){
Object o = array[i];
//do something
}
Object[] array = new Object[100];
for (int i = 0; i < array.length; i++){
Object o = array[i];
//do something
}
Object[] array = new Object[100];
for (Object o : array){
//do something
}
第一个不是常见的习语;我不会那样写的 没有内存或效率差异。第三个是在后来的JVM中添加的语法糖(我相信是JDK6)
您的代码将成为内存和效率的瓶颈,而不是您的循环结构。就内存占用和效率而言,是的。然而,两者之间存在差异。在第一种情况下,
i
在循环之外存在(具有范围);而在第二种情况下,情况并非如此。在第三种情况下,无法(直接)访问索引或更改当前对象位置的数组内容。第三种版本是在Java 5中引入的,旨在简化泛型的工作。它得到了增强,因为在循环之前不需要确定数组中有多少个元素。也不需要指定如何增加当前位置,从而提供更清晰的实现,而无需创建计数器变量或迭代器 不,不完全一样。这很容易验证,我甚至不觉得奇怪
只需反编译以下两个函数:
public static void test1(Object[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public void test2(Object[] arr) {
for(Object o : arr) {
System.out.println(o);
}
}
我只是加入了println(),这样我们就可以看到变量已经完成了一些操作,并确保javac不会对它进行优化。显然,从更大的角度来看,差异并不重要,它们几乎不可测量,但仍然不是相同的代码;)
虽然我不确定第二个函数中到底发生了什么,所以如果有人想花时间剖析代码,请继续;-) 多谢各位。那么在第二条语句中,迭代器只有一个内存分配?或者为每个迭代分配不同的资源?在第三节。。。Java分配隐藏迭代器?数组长度是一个隐藏整数?没错。如果您喜欢冒险,可以使用javap查看为每种循环生成的字节码。它们应该非常相似。哦,我不知道javap。。。再次感谢你!:)@我错过了你先前评论的一部分。每次通过循环都会重新计算数组长度。如果将不同的数组分配给
数组
,则循环测试将考虑新的长度。通过将数组长度分配给一个局部变量并在测试中使用它(或者通过从array.length-1
向下迭代到0
),可以(非常)节省一点成本。我很少引入一个额外的变量来存储数组长度,只是为了进行优化。第一个习惯用法在某些情况下非常有用,如果您想中断循环,然后需要知道是否有中断,如果有,还需要知道触发中断的对象的索引。我同意增强的for循环语法更简洁,前提是循环体中不需要当前索引。(首先,您不必担心主体是否与索引变量有冲突。)但在我看来,它更容易掩盖意外的自动装箱开销(尽管在这种情况下不是这样)。您的第一个示例并不完全跟踪OP的第一个示例。您需要替换System.out.println(arr[i])代码>带有对象o=arr[i];系统输出打印ln(o)代码>以进行公平比较。因此,只有在test2
中,每个数组元素才存储在o
(局部变量#5)中。第二种方法也做了一些不同的事情:它缓存数组的长度(在局部变量#3中),并将arr
复制到另一个局部变量(#2)。这些差异可能是由于编译器应用了不同的字节码模板。
public static void test1(java.lang.Object[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: aload_0
4: arraylength
5: if_icmpge 23
8: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_0
12: iload_1
13: aaload
14: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
17: iinc 1, 1
20: goto 2
23: return
public void test2(java.lang.Object[]);
Code:
0: aload_1
1: astore_2
2: aload_2
3: arraylength
4: istore_3
5: iconst_0
6: istore 4
8: iload 4
10: iload_3
11: if_icmpge 34
14: aload_2
15: iload 4
17: aaload
18: astore 5
20: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
23: aload 5
25: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
28: iinc 4, 1
31: goto 8
34: return
}