Java For循环差异

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

在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 = 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
}