The scope of local variables is a compile-time artifact. This information is already lost, when the compiler (e.g. javac
) produces bytecode from your source code.
Java bytecode references storage within a stack frame, equivalent to local variables, by a positional number. The assignment of local variables to these positions and the calculation of the maximum storage required in a stack frame is done at compile time.
The compiler may reuse storage within a stack frame for variables having disjunct scopes, but is not required to (it usually does). But in your example, there are no variables with disjunct scopes. Within the loop’s body, three variables exist at the same time, temporaryDate
, o
and an unnamed variable holding an Iterator
. Since there is a point where these variable all exists at the same time, they must have different storage positions and the stack frame must have a size of at least three. This applies to both variants, hence, there is no relevant difference.
But since storage within a stack frame can only be reused for variables with disjunct scopes, limiting the scope of variables (which is a good practice anyway) can improve the reuse, e.g. when you write
for(SomeObject o : collectionsOfObjects){
Date temporaryDate = o.getDate();
}
for(OtherObject other : collectionsOfObjects){
String n = other.getName();
}
the storage of all three variables required for the first loop can be reused in the second loop (the different type doesn’t matter). If temporaryDate
was declared outside the loop, reusing its storage in the second loop would be impossible.
Note that the stack frame is allocated at the method entry and destroyed at method exit anyway. Declarations of local variables do not cause an allocation, or any action at all. At runtime, only the actual reads and writes matter. So the way you declare the variables has no performance impact.
When the JVM starts optimizing the code (talking about a sophisticated JVM like HotSpot/OpenJDK), it converts the code into the Static single assignment form, which is likely to look entirely different to your declarations. This form enables fundamental optimization like complete removal of unused variables, folding variables predictably holding the same value into one and eliminating redundant calculations or replacing them with their predicted result.