I like to define loop variables inside the loop on the line where the assignment is happening. For example if I was iterating through a String collection I would do it like below
private void test() {
for (Iterator iter = list.iterator(); iter.hasNext();) {
String str = (String) iter.next();
System.out.println(str);
}
}
The other day a colleague of mine was doing a peer review and he said this was bad and I should have defined the String variable str outside the loop. What he suggested was something like below.
private void test() {
String str;
for (Iterator iter = list.iterator(); iter.hasNext();) {
str = (String) iter.next();
System.out.println(str);
}
}
When I questioned the logic behind it he said something like
If you define str inside the loop it will get initialized in each iteration and that’s bad for performance.
Or something like that… and so the argument started. I mean str is a frigging variable not an object that would get initialized or anything. The compiler wouldn’t go allocating memory to str in each iteration and my belief was that it didn’t matter whether you declare str inside the loop or outside the loop. The compiler wouldn’t care and would generate the same byte code in either case.
I did some googling around and came across this blog which discusses the same thing though his preference was to declare the variable outside the loop. The first example was very similar to what I had in mind but it was with primitives. The second example with StringBuffer is a totally different story from mine.
So I had to do my own test, I wrote another class with the str declared outside the loop and compiled them both. Then using javap utility that comes with the JDK printed the byte code for both implementations (ie. javap –c –private <classname>)
Byte Code genarated when the variable is declared inside the loop:
private void test();
Code:
0: aload_0
1: getfield #15;
4: invokevirtual #22;
7: astore_1
8: goto 28
11: aload_1
12: invokeinterface #26,
17: checkcast #32;
20: astore_2
21: getstatic #34;
24: aload_2
25: invokevirtual #40;
28: aload_1
29: invokeinterface #46,
34: ifne 11
37: return
}
Byte Code genarated when the variable is declared outside the loop:
private void test();
Code:
0: aload_0
1: getfield #15;
4: invokevirtual #22;
7: astore_2
8: goto 28
11: aload_2
12: invokeinterface #26,
17: checkcast #32;
20: astore_1
21: getstatic #34;
24: aload_1
25: invokevirtual #40;
28: aload_2
29: invokeinterface #46,
34: ifne 11
37: return
}
Basically it’s the same byte code except the variable numbers are switched (ie. line 11 aload_1 become aload_2). So it really doesn't make a difference and where you declare the variable is a just a matter of taste.