环境: JDK1.8 Windows 10
example1:
String msg=null;
for (int i=0;i<10;i++){
msg="Hello";
}
和示例2:
for(int =0;i<10;i++){
String msg = "hello";
}
谁能告诉我这两个例子之间的区别 以及哪种代码更有效
答案 0 :(得分:3)
在第一个示例中,msg
在所示的最外部范围内是范围内的,而在第二个示例中,msg
仅在循环体中处于范围内。在继续之前,我会提醒读者,过早的优化(尤其是此处所见的微优化)通常并不适当或没有用,因此人们应该首先争取清晰,可读和可维护的代码。
我现在继续为好奇的读者。通过使用javac
编译代码
1.8.0_171并用javap -c
进行反汇编,我得到以下字节码:
第一种方法:
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: iload_2
5: bipush 10
7: if_icmpge 19
10: ldc #2 // String f
12: astore_1
13: iinc 2, 1
16: goto 4
19: return
第二种方法:
Code:
0: iconst_0
1: istore_1
2: iload_1
3: bipush 10
5: if_icmpge 17
8: ldc #2 // String f
10: astore_2
11: iinc 1, 1
14: goto 2
17: return
如您所见,这两个编译结果在本质上非常相似。两者都具有循环结构,循环的主体由负载常数(ldc)和后跟astore_<n>
的局部变量插槽组成。变量对插槽的分配有所不同(第一个将i
分配给插槽2,msg
分配给1,第二个相反),但这不会产生重大影响。第一个确实包含两个额外的字节码,用于在第一次迭代之前将null
到msg
存储。但是,这种影响非常微小,以至于无法尝试对此进行优化。
我目前没有工具集来查看JIT优化产生的机器代码,但我强烈怀疑任何有能力的JIT编译器都会优化整个循环。