0

Possible Duplicate:
Declaring variables inside or outside of a loop

Please consider these 2 samples of Java code:

// 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
}

Is there any difference in performance/memory consumption between the samples? If it is, then does it depend on type of a handle (an Object vs. a primitive)?

Community
  • 1
  • 1
Vit Khudenko
  • 28,288
  • 10
  • 63
  • 91
  • 3
    I cannot imagine that this makes any difference in the compiled bytecode. You could check with javap. The first version is much more readable, though, and does not "leak scope". – Thilo Sep 27 '12 at 07:54
  • I could see only one difference. In second case foo and bar will be available outside loop. – Amit Deshpande Sep 27 '12 at 07:57

2 Answers2

8

It makes a difference in terms of the byte code generated but no difference in terms of performance.

What is far more important is making the code as simple, self contained and maintainable as possible. For this reason I would prefer the first example.

BTW: Simpler code is often optimised better because its easier for the JIT to optimise as much as it can. Confusing code will also confuse the JIT and it will prevent optimisations being used.

If you use ASMifierClassVisitor which dumps the raw byte code in a readable form (and can be turned back into the original byte code) You will see that javap glosses over some of the details which are not so important.

If I compare (on the left below) at 951 bytes long.

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
}

with (on the right below) and 935 bytes long.

List<Item> items = new ArrayList<Item>();

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

You can see at the very least the debug line numbers must be different, but also some of the code is different as well as the local variables defined in a different order and given different allocation numbers.

enter image description here

You can right click => View Image to see the image better.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 3
    According to the link I posted, same bytecode... – assylias Sep 27 '12 at 07:57
  • Agree with "prefer first example". Perhaps even making them `final`. – Thorbjørn Ravn Andersen Sep 27 '12 at 07:58
  • @Peter: thanks for the answer! Of course, I understand the risks of an unneeded extending a smth's scope. The question was just about performance (I should have underlined that in the question). Since the resulting byte-code turns to be exactly the same - there is no difference in performance. – Vit Khudenko Sep 27 '12 at 08:12
  • 2
    `javap` shows its much the same byte code in important details. But at a minimum the lines number can't be the same. – Peter Lawrey Sep 27 '12 at 08:18
  • @PeterLawrey I'm not sure I follow you - in the end, the JVM will interpret the bytecode (which is the same in both cases), not some reverse-engineered bytecode - or am I missing something? – assylias Sep 27 '12 at 08:27
  • 1
    @assylias What is the difference between the byte code and the reverse engineered byte code? The `.class` file sizes are not the same so their contents can't be the same. – Peter Lawrey Sep 27 '12 at 08:32
  • You don't need to use ASMifier after all, you just need to use `javap -c -v` to see the differences. – Peter Lawrey Sep 27 '12 at 08:37
1

If you're worried about leaking scope in the 2nd example, you can also limit the scope by putting it in a block:

{
    Foo foo;
    int bar;
    for (Item item : items) {
        foo = item.getFoo();
        bar = item.getBar();
        // do smth with foo and bar
    }
}
lilalinux
  • 2,903
  • 3
  • 43
  • 53
  • 2
    In this case, yes. But in general, this could still lead to values being accidentally carried over to the next iteration of the loop. – Thilo Sep 27 '12 at 08:02