16

Does it make a difference if I declare variables inside or outside a loop in Java?

Is this

for(int i = 0; i < 1000; i++) {
   int temp = doSomething();
   someMethod(temp);
}

equal to this (with respect to memory usage)?

int temp = 0;
for(int i = 0; i < 1000; i++) {
   temp = doSomething();
   someMethod(temp);
}

And what if the temporary variable is for example an ArrayList?

for(int i = 0; i < 1000; i++) {
   ArrayList<Integer> array = new ArrayList<Integer>();
   fillArray(array);
   // do something with the array
}

EDIT: with javap -c I got the following output

Variable outside the loop:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iconst_0      
       3: istore_2      
       4: iload_2       
       5: sipush        1000
       8: if_icmpge     25
      11: invokestatic  #2                  // Method doSomething:()I
      14: istore_1      
      15: iload_1       
      16: invokestatic  #3                  // Method someMethod:(I)V
      19: iinc          2, 1
      22: goto          4
      25: return  

Variable inside the loop:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     23
       9: invokestatic  #2                  // Method doSomething:()I
      12: istore_2      
      13: iload_2       
      14: invokestatic  #3                  // Method someMethod:(I)V
      17: iinc          1, 1
      20: goto          2
      23: return        

And for the interested, this code:

public class Test3 {
    public static void main(String[] args) {
        for(int i = 0; i< 1000; i++) {
            someMethod(doSomething());
        }   
    }
    private static int doSomething() {
        return 1;
    }
    private static void someMethod(int temp) {
        temp++;
    }
}

produces this:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iload_1       
       3: sipush        1000
       6: if_icmpge     21
       9: invokestatic  #2                  // Method doSomething:()I
      12: invokestatic  #3                  // Method someMethod:(I)V
      15: iinc          1, 1
      18: goto          2
      21: return   

But the optimization happens at runtime then. Is there a way to look at the optimized code? (Sorry for the long EDIT)

3
  • 1
    I'm pleased you actually looked at the disassembly and hope it taught you something. I had hoped someone with actual Java experience would answer your final question about the optimized code, but perhaps you can post that specific part over on Stackoverflow - it seems to be a very concrete question. Oct 8, 2012 at 15:41
  • Yes, I will try to get the optimized code. (The question changed a bit, I asked the thing with the optimized code in the edit)
    – Puckl
    Oct 8, 2012 at 15:49
  • 1
    Answered here
    – Aven Desta
    Mar 31, 2021 at 10:25

5 Answers 5

7

The common answer to most of these questions should be "why don't you try it and find out?". In Java you could probably take a look at the generated bytecode (I believe the tool is called javap), to see what the difference in byte code is between those two ways of declaring the variable.

Doing it like that is a better learning experience for you, because next time you're running into an optimization issue you can use the same tool to verify that the compiler is doing what you are expecting - it will help you avoid needlessly changing your coding style when the optimizer does fine on its own, or finding actual tweaks when you really need that last bit of performance.

0
6

Short answer : no. There were similar questions somewhere on this site already. There is no notable difference as per the generated bytecode. Declaring them when needed produces less lines of code.

4
  • What about the performance when you create a new object inside the loop, that could just as well be created only once?
    – Bubblewrap
    Oct 8, 2012 at 12:59
  • 3
    In this case obviously there is performance and memory penalty. But it is not quite the case in the op's question
    – Kemoda
    Oct 8, 2012 at 13:27
  • 5
    Link is broken.
    – Zon
    Jan 10, 2016 at 9:25
  • Answered Here
    – Aven Desta
    Mar 31, 2021 at 10:25
2

At the level of the individual variable there is no significant difference in effeciency, but if you had a function with 1000 loops and 1000 variables (never mind the bad style implied) there could be systemic differences because all the lives of all the variables would be the same instead of overlapped. This could affect things like stack size and the garbage collector's ability to clean up the variables that were being kept alive longer than necessary.

Also, it's much better style to give variables the smallest possible scope. It prevents accidents.

4
  • This is not true - at the JVM level, there is no such thing as limited scope for local variables. Oct 8, 2012 at 9:46
  • do you mean that if I write for(int i= ..) 1000 times, there will be 1000 different variables on the stack when I exit the function?
    – ddyer
    Oct 8, 2012 at 9:55
  • according to artima.com/insidejvm/ed2/jvm8.html "For example, if two local variables have limited scopes that don't overlap, such as the i and j local variables in Example3b, compilers are free to use the same array entry for both variables. " And that only makes sense, compilers are free to optimize the size of the stack frame in this way.
    – ddyer
    Oct 8, 2012 at 10:09
  • 1
    Good point; but if we're talking about compiler optimizations, the compiler can almost as easily reuse local variable entries for variables that have overlapping lexical scope but are not used in an overlapping manner. Oct 8, 2012 at 10:43
2

Who cares about memory usage for a single variable of type int? Nobody. But there is one huge difference if your code is a bit more complicated:

If there are situations where the code inside the loop misses initialising temp then it will without any warning use the value of the previous iteration. If this happens only rarely then you have a very hard to find bug. If you declare temp inside the loop, and the code inside the loop misses initialising temp, then the compiler will tell you about your error.

Always write your code so that the compiler has a chance to find stupid mistakes that you make. A corrolary is that you don't initialise a variable until you have the actual value that should be stored, and not a placeholder like 0.

-1

If you do a 1000-2000 loop using the two methods, you will find out that declaring it outside is more economical and better optimized. Reason being, re-initialization of the variable in the loop leads to creation of memory location (different ones) for the variable. The extra workload and time lag that is given to the code for the reallocation of memory for variable during the loop traversing leads to a difference in execution time.

1
  • 1
    Have you actually tried this and shown there is a difference? If so, which JVM were you using on which platform? Dec 29, 2020 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.