您可以编译方法并比较它们的字节码以查看差异。
最大的区别在于func1 和func2 之间,其中func1 只调用一次size(),而func2 每次迭代都会重新调用size()。如果size() 没有被缓存(大多数实现都会缓存它),那么重新计算它可能会很昂贵。即使在那种情况下,抖动也可能会优化它,尤其是使用局部变量,因为它可能会意识到列表不会改变。但是,如果列表是公开的成员,那么它可能需要每次重新计算大小,因为单独的线程可能已经修改了列表,尽管它仍然很有可能被优化以假设大小没有改变。
func3 和fun4 之间的唯一区别是func4 使用了额外的astore 和aload,因为它将列表存储在局部变量中,这可能会被抖动优化掉。
最终,测试效率的最佳方法是衡量它。
private void func1() {
ArrayList<String> list = new ArrayList<>();
int x = list.size();
for (int i = 0; i < x; i++)
System.out.println(list.get(i));
}
private void func2() {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < list.size(); i++)
System.out.println(list.get(i));
}
private void func3() {
for (String str : new ArrayList<String>())
System.out.println(str);
}
private void func4() {
ArrayList<String> list = new ArrayList<>();
for (String str : list)
System.out.println(str);
}
private void func1();
... storing the list ...
8 aload_1 [list]
9 invokevirtual java.util.ArrayList.size() : int [18] // compute list.size()
12 istore_2 [x] // store list.size()
13 iconst_0
14 istore_3 [i]
15 goto 35
... print ...
32 iinc 3 1 [i] // i++
35 iload_3 [i] // load i
36 iload_2 [x] // load the already computed list.size()
37 if_icmplt 18 // if i < list.size() goto 18
40 return
private void func2();
... storing the list ...
8 iconst_0
9 istore_2 [i]
10 goto 30
... print ...
27 iinc 2 1 [i] // i++
30 iload_2 [i] // load i
31 aload_1 [list] // load the list
32 invokevirtual java.util.ArrayList.size() : int [18] // compute list.size()
35 if_icmplt 13 // if i < list.size() goto 13
38 return
private void func3();
... storing the list ...
7 invokevirtual java.util.ArrayList.iterator() : java.util.Iterator [50]
10 astore_2
11 goto 31
14 aload_2
15 invokeinterface java.util.Iterator.next() : java.lang.Object [54] [nargs: 1]
... print ...
31 aload_2
32 invokeinterface java.util.Iterator.hasNext() : boolean [60] [nargs: 1]
37 ifne 14
40 return
private void func4();
... storing the list ...
7 astore_1 [list] // these are the only extra operations
8 aload_1 [list] // to store the list in a local variable
9 invokevirtual java.util.ArrayList.iterator() : java.util.Iterator [50]
12 astore_3
13 goto 33
16 aload_3
17 invokeinterface java.util.Iterator.next() : java.lang.Object [54] [nargs: 1]
... print ...
33 aload_3
34 invokeinterface java.util.Iterator.hasNext() : boolean [60] [nargs: 1]
39 ifne 16
42 return