Reputation: 716
One common dilemma I have faced throughout programming is regarding declaring variables inside a loop. Say I have to perform something like the following:
List list=myObject.getList();
Iterator itr=list.iterator();
while (itr.hasNext()){
BusinessObject myBo=(BusinessObject)itr.next();
process(myBo);
}
In the above snippet, should myBo
be declared outside the loop or does declaring it inside the loop not cause harm to memory and performance?
Upvotes: 8
Views: 2661
Reputation: 33517
Just have a look at the byte code with javap -c [ClassName]
. Here's a class demonstrating a few examples of single-use variables with loops. The relevant bytecode dump is in the comments:
class HelloWorldLoopsAnnotated {
//
// HelloWorldLoopsAnnotated();
// Code:
// 0: aload_0
// 1: invokespecial #1; //Method java/lang/Object."<init>":()V
// 4: return
////////////////////////////////////////////////////////////////////////////
void stringDeclaredInsideLoop(){
while (true) {
// 0: ldc #2; //String Hello World!
String greeting = "Hello World!";
doNothing(greeting);
}
}
//
// void stringDeclaredInsideLoop();
// Code:
// 0: ldc #2; //String Hello World!
// 2: astore_1
// 3: aload_0
// 4: aload_1
// 5: invokespecial #3; //Method doNothing:(Ljava/lang/String;)V
// 8: goto 0
////////////////////////////////////////////////////////////////////////////
void stringDeclaredOutsideLoop(){
String greeting;
while (true) {
greeting = "Hello World!";
doNothing(greeting);
}
}
//
// void stringDeclaredOutsideLoop();
// Code:
// 0: ldc #2; //String Hello World!
// 2: astore_1
// 3: aload_0
// 4: aload_1
// 5: invokespecial #3; //Method doNothing:(Ljava/lang/String;)V
// 8: goto 0
////////////////////////////////////////////////////////////////////////////
void stringAsDirectArgument(){
while (true) {
doNothing("Hello World!");
}
}
// void stringAsDirectArgument();
// Code:
// 0: aload_0
// 1: ldc #2; //String Hello World!
// 3: invokespecial #3; //Method doNothing:(Ljava/lang/String;)V
// 6: goto 0
////////////////////////////////////////////////////////////////////////////
private void doNothing(String s) {
}
}
stringDeclaredInsideLoop()
and stringDeclaredOutsideLoop()
yield identical six-instruction bytecode. stringDeclaredInsideLoop()
does still win: limited scope is best.
After some contemplation, I can't really see how tightening scope would ever affect performance: identical data in the stack would necessitate identical instructions.
stringAsDirectArgument()
, however, defines the operation in only four instructions. Low memory environments (e.g. my magnificently dumb phone) may appreciate the optimization while a colleague reading your code may not, so exercise judgement before shaving bytes from your code.
See the full gist for more.
Upvotes: 1
Reputation: 26586
myBo
is simply a reference to an object (that is returned by itr.next()). As such the amount of memory that it needs is very small, and only created once, and adding it inside the loop should not affect your program. IMO, declaring it inside the loop where it is used actually helps make it more readable.
Upvotes: 4
Reputation: 199215
It doesn't cause any memory harm.
BTW unless you're omitting some code you may skip the declaration altogether:
while (itr.hasNext()){
//BusinessObject myBo=(BusinessObject)itr.next();
process((BusinessObject)itr.next());
}
Upvotes: 2
Reputation: 39733
The most elegant solution for your loop would be an enhanced for loop (java 5 or newer):
List<BusinessObject> list = myObject.getList();
for( BusinessObject myBo : list ) {
process(myBo);
}
But even with the code you provided there will be no performance problem, because all the temporary variables only hold references to the BusinessObject, which is very cheap.
Upvotes: 4
Reputation: 3455
The temporary reference myBo
is put on stack and should mostly be optimized away. There shouldn't be any performance penalty in your code.
Upvotes: 0
Reputation: 160
If short -- no.
In C++ it could be a problem if myBo is created by copying
but in Java there is always used references, is'nt it?
for performance, its better to optimize something you are do in process()
Upvotes: 1
Reputation: 67750
One principle of good software design is to limit the scope of local variables, i.e. to declare them just in time within a block that ends soon after the last use of that variable. This doesn't affect performance or other "hard" aspects but makes the program more readable and easier to analyze.
In summary, doing what you're doing is considered GOOD.
Upvotes: 5
Reputation: 5748
If possible use List<BusinessObject>
and Iterator<BusinessObject>
to avoid casting:
List<BusinessObject> list = myObject.getList();
Iterator<BusinessObject> itr = list.iterator();
while (itr.hasNext()) {
process(itr.next());
}
Upvotes: 5
Reputation: 92026
Declaring it inside the loop won't cause any harm to the memory and performance.
Upvotes: 8