Java中循环的局部变量初始化最有效的方法是什么?

Java中循环的局部变量初始化最有效的方法是什么?,java,performance,variables,loops,Java,Performance,Variables,Loops,可能重复: 请考虑这2个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 = i

可能重复:

请考虑这2个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
}

样本之间的性能/内存消耗是否存在差异?如果是,那么它是否取决于句柄的类型(对象与原语)?

它在生成的字节码方面产生差异,但在性能方面没有差异

更重要的是使代码尽可能简单、自包含和可维护。出于这个原因,我更喜欢第一个例子

顺便说一句:简单的代码通常会得到更好的优化,因为JIT更容易进行尽可能多的优化。混淆代码也会混淆JIT,并且会阻止使用优化

如果您使用which以可读的形式转储原始字节码(并且可以转换回原始字节码),您将看到
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
}
List<Item> items = new ArrayList<Item>();

for (Item item : items) {
    Foo foo = item.getFoo();
    int bar = item.getBar();
    // do something with foo and bar
}
List items=new ArrayList();
富富,;
int-bar;
用于(项目:项目){
foo=item.getFoo();
bar=item.getBar();
//用foo和bar做点什么
}
具有(在下面的右侧)和935字节长

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
}
List<Item> items = new ArrayList<Item>();

for (Item item : items) {
    Foo foo = item.getFoo();
    int bar = item.getBar();
    // do something with foo and bar
}
List items=new ArrayList();
用于(项目:项目){
Foo-Foo=item.getFoo();
int bar=item.getBar();
//用foo和bar做点什么
}
您至少可以看到调试行号必须不同,但某些代码以及以不同顺序定义并给定不同分配号的局部变量也不同


您可以
右键单击
=>
查看图像
以更好地查看图像。

如果您担心第二个示例中的范围泄漏,您也可以通过将其放在块中来限制范围:

{
    Foo foo;
    int bar;
    for (Item item : items) {
        foo = item.getFoo();
        bar = item.getBar();
        // do smth with foo and bar
    }
}

我无法想象这会对编译的字节码产生任何影响。您可以使用javap进行检查。不过,第一个版本更具可读性,并且没有“泄漏范围”。我只能看到一个区别。在第二种情况下,foo和bar将在循环外可用。根据我发布的链接,相同的字节码…同意“首选第一个示例”。甚至可能让它们成为最后的@Peter:谢谢你的回答!当然,我理解不必要地扩大smth范围的风险。问题只是关于性能(我应该在问题中强调这一点)。由于生成的字节码完全相同,因此性能没有差异。
javap
在重要细节中显示了几乎相同的字节码。但至少行号不能相同。@assylias字节码和反向工程字节码之间的区别是什么?
.class
文件大小不同,因此它们的内容不能相同。在这种情况下,是的。但一般来说,这仍然可能导致值意外地传递到循环的下一个迭代中。