I have the following code:
public class BookLib {
void f() {
final int x = 5; // Line 1
class MyCLass {
void print() {
System.out.println(x);
}
}
}
}
I don't understand why should use final variable in this case (Line 1)?
Here you create an inner class. In order to access the context of execution, the references to the variables should stay intact, otherwise an error behaviour is observed. In order to guarantee this, you should declare your variable final: thus one can't change it.
See detailed explanation here.
So you have a local final variable and method-local inner class. A method-local inner class cannot use non-final variables declared within method (including parameters).
To go more deeply into this: Method-local inner class can be instantiated only within method where the class is defined. The local variables live on stack for the lifetime of the method. As the method ends, the local variables disappear, however the inner class object created still lives.
It's a matter of lifetime/scope.
You've created an inner class here. Since the life-time of objects of this class can potentially be much greater than the runtime of the method invocation (i.e. the object can still exist long after the method has returned), it needs to "preserve" the state of local variables that it can access.
This preserving is done by creating an (invisible, synthetic) copy inside the inner class and automatically replacing all references to the local variable with references to that copy. This could lead to strange effects when the local variable were modified after the inner class object was created.
To avoid this, there is a requirement that all local variables that you access this way are
final
: this ensures that there is only ever one possible value for the local variable and no inconsistencies are observed.This specific rule can be found in §8.1.3 Inner Classes and Enclosing Instances of the JLS:
From kathy sierra scjp Book
The local variables of the method live on the stack, and exist only for the lifetime of the method. We already know that the scope of a local variable is limited to the method the variable is declared in. When the method ends, the stack frame is blown away and the variable is history. But even after the method completes, the inner class object created within it might still be alive on the heap if, for example, a reference to it was passed into some other code and then stored in an instance variable. Because the local variables aren't guaranteed to be alive as long as the method-local inner class object, the inner class object can't use them. Unless the local variables are marked final!