Accessing local variables even after methods finish (in Java)

Submitted by Kamal Wickramanayake on December 3, 2010 - 01:42

At times we write methods in Java classes with local variables that we need to access even after the methods finish execution. Here's an example:


public class FinalLocalVariableTest {

    public static void main(String[] args) {
        final int x = 5;

        Runnable r = new Runnable() {            
            public void run() {
                System.out.println("x is " + x);

        Thread t = new Thread(r);

Note that within the inner class 'x' is being accessed which is a local variable. Since 'r' is passed to a new Thread, this Runnable created may live even after the method (in this case the main() method) finishes.

In Java, memory is allocated for local variables in frames associated with the method execution stack. When a method finishes, the frame disappears and the memory allocated for local variables is no longer needed and is reused. But then, what happens to 'x'? We continue to access it within the Runnable even after the method finishes. 'x' should live even after the method execution frame is removed from the stack.

Java wants you to declare such local variables directly accessed within inner class code as final.

What happens when you start using the final local variable in an inner class is that the inner class gets a copy of the field. The inner classes in fact never access the method execution frame allocated variable. Read this:

"An anonymous local class can use local variables because the compiler automatically gives the class a private instance field to hold a copy of each local variable the class uses. The compiler also adds hidden parameters to each constructor to initialize these automatically created private fields. Thus, a local class does not actually access local variables, but merely its own private copies of them. The only way this can work correctly is if the local variables are declared final, so that they are guaranteed not to change. With this guarantee in place, the local class is assured that its internal copies of the variables accurately reflect the actual local variables."

So, that resolves the mystery of how an inner class continues to access a final local variable even after the method (that declares final local variables) runs into completion.