Java Reference
In-Depth Information
declared final or are effectively final. In other words, lambda expressions can capture local
variables that are assigned to them only once. (Note: capturing an instance variable can be seen
as capturing the final local variable this.) For example, the following code doesn't compile
because the variable portNumber is assigned to twice:
Restrictions on local variables
You may be asking yourself why local variables have these restrictions. First, there's a key
difference in how instance and local variables are implemented behind the scenes. Instance
variables are stored on the heap, whereas local variables live on the stack. If a lambda could
access the local variable directly and the lambda were used in a thread, then the thread using the
lambda could try to access the variable after the thread that allocated the variable had
deallocated it. Hence, Java implements access to a free local variable as access to a copy of it
rather than access to the original variable. This makes no difference if the local variable is
assigned to only once—hence the restriction.
Second, this restriction also discourages typical imperative programming patterns (which, as we
explain in later chapters, prevent easy parallelization) that mutate an outer variable.
Closure
You may have heard of the term closure and may be wondering whether lambdas meet the
definition of a closure (not to be confused with the Clojure programming language). To put it
scientifically, a closure is an instance of a function that can reference nonlocal variables of that
function with no restrictions. For example, a closure could be passed as argument to another
function. It could also access and modify variables defined outside its scope. Now Java 8
lambdas and anonymous classes do something similar to closures: they can be passed as
argument to methods and can access variables outside their scope. But they have a restriction:
they can't modify the content of local variables of a method in which the lambda is defined.
Those variables have to be implicitly final. It helps to think that lambdas close over values rather
than variables . As explained previously, this restriction exists because local variables live on the
stack and are implicitly confined to the thread they're in. Allowing capture of mutable local
variables opens new thread-unsafe possibilities, which are undesirable (instance variables are
fine because they live on the heap, which is shared across threads).
Search WWH ::




Custom Search