Lambdas: local variables need final, instance variables don't

The fundamental difference between a field and a local variable is that the local variable is copied when JVM creates a lambda instance. On the other hand, fields can be changed freely, because the changes to them are propagated to the outside class instance as well (their scope is the whole outside class, as Boris pointed out below).

The easiest way of thinking about anonymous classes, closures and labmdas is from the variable scope perspective; imagine a copy constructor added for all local variables you pass to a closure.


In document of project lambda : State of the Lambda v4

Under Section 7. Variable capture, It is mentioned that....

It is our intent to prohibit capture of mutable local variables. The reason is that idioms like this:

int sum = 0;
list.forEach(e -> { sum += e.size(); });

are fundamentally serial; it is quite difficult to write lambda bodies like this that do not have race conditions. Unless we are willing to enforce—preferably at compile time—that such a function cannot escape its capturing thread, this feature may well cause more trouble than it solves.

Edit :

Another thing to note here is, local variables are passed in constructor of inner class when you access them inside your inner class, and this won't work with non final variable because value of non-final variables can be changed after construction.

While in case of instance variable, compiler passes reference of class and class' reference will be used to access instance variable. So it is not required in case of instance variables.

PS : It is worth mentioning that, anonymous classes can access only final local variables (in JAVA SE 7), while in Java SE 8 you can access effectively final variables also inside lambda as well as inner classes.