Amit
Amit

Reputation: 716

Variable declaration inside a loop

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

Answers (9)

fny
fny

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

MAK
MAK

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

OscarRyz
OscarRyz

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

tangens
tangens

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

bryantsai
bryantsai

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

user204724
user204724

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

Carl Smotricz
Carl Smotricz

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

cyborg
cyborg

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

missingfaktor
missingfaktor

Reputation: 92026

Declaring it inside the loop won't cause any harm to the memory and performance.

Upvotes: 8

Related Questions