局部变量的范围如何影响 Java 上的加载/存储性能?

环境: JDK1.8 Windows 10


示例1:


String msg=null;

for (int i=0;i<10;i++){

     msg="Hello";

 }

和示例2:


for(int =0;i<10;i++){

      String msg = "hello";

}

谁能告诉我这两个例子的区别,哪个代码效率更高


慕哥6287543
浏览 124回答 1
1回答

阿晨1998

在第一个示例中,msg在显示的最外层作用域中处于作用域内,而msg在第二个示例中仅在循环体中处于作用域内。在我继续之前,我会提醒读者,过早的优化,尤其是这里看到的微优化,通常并不合适或有用,首先应该争取清晰、可读和可维护的代码。我现在将继续为好奇的读者。通过使用javac 1.8.0_171编译代码并使用 反汇编javap -c,我得到以下字节码:第一种方法:&nbsp; &nbsp; Code:&nbsp; &nbsp; &nbsp; &nbsp;0: aconst_null&nbsp; &nbsp; &nbsp; &nbsp;1: astore_1&nbsp; &nbsp; &nbsp; &nbsp;2: iconst_0&nbsp; &nbsp; &nbsp; &nbsp;3: istore_2&nbsp; &nbsp; &nbsp; &nbsp;4: iload_2&nbsp; &nbsp; &nbsp; &nbsp;5: bipush&nbsp; &nbsp; &nbsp; &nbsp; 10&nbsp; &nbsp; &nbsp; &nbsp;7: if_icmpge&nbsp; &nbsp; &nbsp;19&nbsp; &nbsp; &nbsp; 10: ldc&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // String f&nbsp; &nbsp; &nbsp; 12: astore_1&nbsp; &nbsp; &nbsp; 13: iinc&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2, 1&nbsp; &nbsp; &nbsp; 16: goto&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4&nbsp; &nbsp; &nbsp; 19: return第二种方法:&nbsp; &nbsp; Code:&nbsp; &nbsp; &nbsp; &nbsp;0: iconst_0&nbsp; &nbsp; &nbsp; &nbsp;1: istore_1&nbsp; &nbsp; &nbsp; &nbsp;2: iload_1&nbsp; &nbsp; &nbsp; &nbsp;3: bipush&nbsp; &nbsp; &nbsp; &nbsp; 10&nbsp; &nbsp; &nbsp; &nbsp;5: if_icmpge&nbsp; &nbsp; &nbsp;17&nbsp; &nbsp; &nbsp; &nbsp;8: ldc&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // String f&nbsp; &nbsp; &nbsp; 10: astore_2&nbsp; &nbsp; &nbsp; 11: iinc&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1, 1&nbsp; &nbsp; &nbsp; 14: goto&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2&nbsp; &nbsp; &nbsp; 17: return如您所见,两个编译结果在本质上非常相似。两者都具有循环结构,循环体由负载常量 (ldc) 和astore_<n>一个局部变量槽组成。变量对槽的分配是不同的(第一个分配i给槽 2 和msg1,第二个则相反)但这应该不会产生显着影响。第一个确实包括两个额外的字节码,null以便msg在第一次迭代之前存储。然而,这种影响是如此微小,以至于尝试优化它是没有意义的。我目前没有工具集来查看 JIT 优化产生的机器代码,但我强烈怀疑整个循环会被任何有能力的 JIT 编译器优化掉。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java