Srinivas Srinivas - 5 months ago 11
Java Question

Accessing local variables from method local inner class in which we declare the inner class

I am learning Java, the tutorial i am following says Java does not allow the variable k (local variable to m1() in the below example) to be directly accessible from method m2() because they are created in the same method m1() and that I will get an error during compile time (unless k is declared as final). The reason they say is a local variable (k) is created during method is called and destroyed after the method execution is complete, but an object (o) is created when the object is instantiated and can still be not destroyed after method execution. So the tutorial says that if you call the method m2() or object o after method m2 is executed (I do not know how it is possible) variable k will be destroyed and will not be available. So the tutorial claims that Java will not allow such declarations. (Please feel free to correct me wherever my understanding is wrong)

But when I compile this program works fine. Am I missing something? I understand this is a bit complex from my perspective of explaining so if my question is clear so please feel free to ask me if something is not clear.

Thanks in advance for your help.

class innerclass_ex8
{
int x = 10;
static int y = 20;

public void m1()
{
int k = 30;
final int z = 50;
class inner {
public void m2()
{
System.out.println(x);
System.out.println(y);
System.out.println(k);
System.out.println(z);
}
}
inner o = new inner();
o.m2();

}
public static void main(String[] args)
{
innerclass_ex8 g = new innerclass_ex8();
g.m1();
}
}

Answer

First of all, your program compiles and works fine because you are using Java 8. If using Java 7 or lower, it won't even compile.

The reason is exactly as you cited. But I will try to explain it a bit more. Consider the following code:

public void m1() {
    int k = 30;
    class inner {
        public void m2() {
            System.out.println(k);
        }
    }
    inner o = new inner();
    k = 42;     // <= Note the reassignment here.
    o.m2();
}

What should the method call o.m2() print? "30" or "42"? Both outputs could reasonably be argumented. At the time the method was declared and defined, the variable k had the value 30. At the time the method was called, the variable k had the value 42.

To prevent such ambiguities, the compiler does not allow assignment to a variable that is used in such inner classes (local and anonymous). So it must be final.

In Java 8 this was relaxed a bit. Java 8 introduced the concept of effectively final. A variable that is declared and initialized and not being assigned again is considered effectively final. And the compiler allows that code without declaring the variable final.

As a matter of fact, you also get a compiler error in Java 8 when trying to compile the above code.