I have a friend who told me the following but I couldn't give a good reason why.
someArray =.........
int a;
for(int i=0; i < someArray; i++) {
a=someArray.get(i).length();
// Do something
}
He told me that he declared a
outside of the for loop in order to avoid frequent garbage collection.
I thought declaring a
inside of the for loop is more readable and thread safe.
However I couldn't disagree that different instances a
no of iteration will be garbage collected if it's declared inside of for loop.
Any advise for me?
Garbage collection handles objects. What you have is a primitive local variable a
which will be allocated on the stack.
Therefore the whole premise of this question is wrong.
Try decompiling both versions:
void outside(List<String> someArray) {
// I've declared this outside the for loop too in order that the
// the variables i and a are numbered the same in the two versions -
// this makes no difference with respect to a.
int i;
int a;
for(i=0; i < someArray.size(); i++) {
a=someArray.get(i).length();
// Do something
}
}
void inside(List<String> someArray) {
for(int i=0; i < someArray.size(); i++) {
int a=someArray.get(i).length();
// Do something
}
}
The resulting bytecode is identical, so there is no performance or behavioural difference.
As such, you should use the one which is more readable, and has variables in tighter scope: declare the variable inside the loop.
void outside(java.util.List<java.lang.String>);
Code:
0: iconst_0
1: istore_2
2: iload_2
3: aload_1
4: invokeinterface #2, 1 // InterfaceMethod java/util/List.size:()I
9: if_icmpge 32
12: aload_1
13: iload_2
14: invokeinterface #3, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
19: checkcast #4 // class java/lang/String
22: invokevirtual #5 // Method java/lang/String.length:()I
25: istore_3
26: iinc 2, 1
29: goto 2
32: return
void inside(java.util.List<java.lang.String>);
Code:
0: iconst_0
1: istore_2
2: iload_2
3: aload_1
4: invokeinterface #2, 1 // InterfaceMethod java/util/List.size:()I
9: if_icmpge 32
12: aload_1
13: iload_2
14: invokeinterface #3, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
19: checkcast #4 // class java/lang/String
22: invokevirtual #5 // Method java/lang/String.length:()I
25: istore_3
26: iinc 2, 1
29: goto 2
32: return
Since a
is not an object which gets created with every loop iteration it will not be garbage collected at all.
Local, non object data types like int, float, bool,... are being kept on a stack. If the variable is out of scope they will be popped from the stack.
In case a
would be an object the reference to the object would be removed with every iterration causing the object itself to become not referenced anymore which means it will be GCed at some point in the future.
More information: (Chapter 2.6)
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html