Java中循环局部变量初始化的最有效方法是啥? [复制]
Posted
技术标签:
【中文标题】Java中循环局部变量初始化的最有效方法是啥? [复制]【英文标题】:What is the most efficient way of local variables initialization for a loop in Java? [duplicate]Java中循环局部变量初始化的最有效方法是什么? [复制] 【发布时间】:2012-09-18 22:55:45 【问题描述】:可能重复:Declaring variables inside or outside of a loop
请考虑这两个 Java 代码示例:
// 1st sample
for (Item item : items)
Foo foo = item.getFoo();
int bar = item.getBar();
// do smth with foo and bar
// 2nd sample
Foo foo;
int bar;
for (Item item : items)
foo = item.getFoo();
bar = item.getBar();
// do smth with foo and bar
样本之间的性能/内存消耗有什么不同吗?如果是,那么它是否取决于句柄的类型(对象与原语)?
【问题讨论】:
我无法想象这会对编译的字节码产生任何影响。你可以用javap检查。不过,第一个版本更具可读性,并且不会“泄露范围”。 我只能看到一个区别。在第二种情况下, foo 和 bar 将在循环外可用。 【参考方案1】:它在生成的字节码方面有所不同,但在性能方面没有区别。
更重要的是使代码尽可能简单、自包含和可维护。出于这个原因,我更喜欢第一个例子。
顺便说一句:更简单的代码通常会得到更好的优化,因为 JIT 更容易进行尽可能多的优化。混淆代码也会混淆 JIT,它会阻止优化被使用。
如果您使用ASMifierClassVisitor 以可读形式转储原始字节码(并且可以转换回原始字节码),您会看到javap
掩盖了一些不那么重要的细节。
如果我比较(在左下方)951 字节长。
List<Item> items = new ArrayList<Item>();
Foo foo;
int bar;
for (Item item : items)
foo = item.getFoo();
bar= item.getBar();
// do something with foo and bar
(在右下方)和 935 字节长。
List<Item> items = new ArrayList<Item>();
for (Item item : items)
Foo foo = item.getFoo();
int bar = item.getBar();
// do something with foo and bar
您至少可以看到调试行号必须不同,而且某些代码也不同,以及以不同顺序定义的局部变量并给出不同的分配号。
您可以right click
=> View Image
更好地查看图像。
【讨论】:
根据我发布的链接,相同的字节码... 同意“首选第一个例子”。也许甚至让他们final
。
@Peter:感谢您的回答!当然,我理解不必要地扩大范围的风险。问题只是关于性能(我应该在问题中强调这一点)。由于生成的字节码变得完全相同 - 性能没有差异。
javap
在重要细节中显示了相同的字节码。但至少行数不能相同。
@assylias 字节码和逆向工程字节码有什么区别? .class
文件大小不同,因此它们的内容不能相同。【参考方案2】:
如果您担心第二个示例中的范围泄漏,您还可以通过将其放入块中来限制范围:
Foo foo;
int bar;
for (Item item : items)
foo = item.getFoo();
bar = item.getBar();
// do smth with foo and bar
【讨论】:
在这种情况下,是的。但总的来说,这仍然可能导致值被意外地传递到循环的下一次迭代。以上是关于Java中循环局部变量初始化的最有效方法是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
在不对所有记录执行循环的情况下从数据库中检索特定数据的最有效方法是啥?
用不同的参数和默认值在 Ruby 中初始化类的最有效方法是啥?