Please explain to me how a lambda expression can use and modify instance variables of its enclosing class, but can only use local variables of its enclosing scope. (Unless it is final or effective final?)
My basic question is how instance variables of a class are modifiable from within a lambda and local variables are not, in the context of scope.
At first, we can take a look at the JLS, which states the following:
To understand it better, take a look at this example class:
Output of main is
This is because returning a lambda here is much the same as creating a new anonymous class with
new Consumer<String>() {...}
. Your lambda - an instance ofConsumer<String>
has a reference to the class it has been created in. You could rewrite the returnConsumerWithInstanceVariable to useSystem.out.println(s + LambdaTest.this.string)
, this would do exactly the same. This is why you are allowed to to access (and modify) instance variables.If you have a (effective) final local variable in your method, you can access it because you can access it because it gets copied to your lambda instance.
But, however, if its not final, what do you think should happen in the following context:
Should the value get copied to your instance, but then not get updated when the local variable is updated? That would probably cause confusion, as I think many programmers would expected foo to have the new value "to all of you" after returning this lambda.
If you had a primitive value, it would lay on the stack. So you could not simply reference the local variable, because it could disappear after the end of your method is reached.
You can refer this article - https://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood explained on lambda expressions compilation. As explained lambda expressions/blocks of code are compiled into the anonymous class, these anonymous class are compiled with the name format (
<<Enclosing Class name>>$<<1(Number)>>
), so suppose assume if non final local variables are allowed then compiler cannot trace it from where this local variable is referred as anonymous class' '.class' files are created/compiled with aforementioned format separately like normal java classes.So if local variable is final then compiler creates a final instance in the anoymous class which doesn't create ambiguity to compiler. Refer the link mention above for more information