1/* First of all, your program compiles and works fine because you are using Java 8. 
2If using Java 7 or lower, it won't even compile. The reason is exactly as you cited. 
3But I will try to explain it a bit more. Consider the following code: */
4
5public void m1() {
6    int k = 30;
7    class inner {
8        public void m2() {
9            System.out.println(k); 
10        }
11    }
12    inner o = new inner();
13    k = 42;     // <= Note the reassignment here.
14    o.m2();
15}
16
17/*
18What should the method call o.m2() print? "30" or "42"? Both outputs could 
19reasonably be argumented. At the time the method was declared and defined, 
20the variable k had the value 30. At the time the method was called, the 
21variable k had the value 42.
22
23To prevent such ambiguities, the compiler does not allow assignment to a 
24variable that is used in such inner classes (local and anonymous). So it 
25must be final.
26
27In Java 8 this was relaxed a bit. Java 8 introduced the concept of 
28effectively final. A variable that is declared and initialized and not 
29being assigned again is considered effectively final. And the compiler 
30allows that code without declaring the variable final.
31
32As a matter of fact, you also get a compiler error in Java 8 when trying 
33to compile the above code.  
34*/