Hi Frederick!
When reading JLS "Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final.
Any local variable used but not declared in an inner class must be definitely assigned before the body of the inner class." - why it MUST be declared final by the way?
Or I have to take it for granted? And why it MUST be assigned before the body of the inner class?
I think what you are talking about is something specific to local variables and method-local inner classes. The idea is a if you intent to use a local variable in an inner class of the same method, it is required that that variable should be final.
To see why, let's suppose there were no such requirement. In that case, the following code should compile even though x is not final:
interface Intf { public void printValue(); } public class A { public static Intf getImplementation() { int x = 1; Intf obj = new Intf() { public void printValue() { System.out.println(x); } }; x = 2; return obj; } public static void main(String args[]) { Intf i = getImplementation(); i.printValue(); } }
line-11 to line-15 is an anonymous inner class. (The same idea happens with non-anonymous method-local inner class too, but I used an anonymous inner class for clarity).
Now, as the line-23 runs, line-9 makes x 1 and line-17 makes x 2. As the method completes, there wouldn't be any trace of the local variable 'x'.
Then it comes to line-24, where you try to call the printValue() on the inner class object. What do you think it should print? 1? - because that was the value before the inner class was created? Or 2? because that was the value it had at the end? or 0? as in the default value of int?
The answer is there is no answer! Since x is a method-local variable, it gets discarded from the memory as the method completes. When the line-24 makes the method attempt to print x, you don't have that in the memory anymore.
To overcome this, it requires the variable x to be final. When it is final, the JVM know it is a constant, so the JVM knows that when it says 'x' at the line-13, we are always referring to the same value/object, so it can compile it in a way that in the bytecode, 'x' gets replaced with the value of it, which is a constant.
The reason why it must be assigned before the start of the local method is simply because you can't use a local variable before assigning a value to it - despite of it is a final reference or not.
Does that make it clear?
Thank you for the great explanation, yes, it is clear now!