Java Closures with lambda expressions.

suggest change

A lambda closure is created when a lambda expression references the variables of an enclosing scope (global or local). The rules for doing this are the same as those for inline methods and anonymous classes.

Local variables from an enclosing scope that are used within a lambda have to be final. With Java 8 (the earliest version that supports lambdas), they don’t need to be declared final in the outside context, but must be treated that way. For example:

int n = 0; // With Java 8 there is no need to explicit final
Runnable r = () -> { // Using lambda
    int i = n;
    // do something
};

This is legal as long as the value of the n variable is not changed. If you try to change the variable, inside or outside the lambda, you will get the following compilation error:

“local variables referenced from a lambda expression must be final or effectively final”.

For example:

int n = 0;
Runnable r = () -> { // Using lambda
    int i = n;
    // do something
};
n++; // Will generate an error.

If it is necessary to use a changing variable within a lambda, the normal approach is to declare a final copy of the variable and use the copy. For example

int n = 0;
final int k = n; // With Java 8 there is no need to explicit final
Runnable r = () -> { // Using lambda
    int i = k;
    // do something
};
n++;      // Now will not generate an error
r.run();  // Will run with i = 0 because k was 0 when the lambda was created

Naturally, the body of the lambda does not see the changes to the original variable.

Note that Java does not support true closures. A Java lambda cannot be created in a way that allows it to see changes in the environment in which it was instantiated. If you want to implement a closure that observes or makes changes to its environment, you should simulate it using a regular class. For example:

// Does not compile ...
public IntUnaryOperator createAccumulator() {
    int value = 0;
    IntUnaryOperator accumulate = (x) -> { value += x; return value; };
    return accumulate;
}

The above example will not compile for reasons discussed previously. We can work around the compilation error as follows:

// Compiles, but is incorrect ...
public class AccumulatorGenerator {
    private int value = 0;

    public IntUnaryOperator createAccumulator() {
        IntUnaryOperator accumulate = (x) -> { value += x; return value; };
        return accumulate;
    }
}

The problem is that this breaks the design contract for the IntUnaryOperator interface which states that instances should be functional and stateless. If such a closure is passed to built-in functions that accept functional objects, it is liable to cause crashes or erroneous behavior. Closures that encapsulate mutable state should be implemented as regular classes. For example.

// Correct ...
public class Accumulator {
   private int value = 0;

   public int accumulate(int x) {
      value += x;
      return value;
   }
}

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


Lambda Expressions:
* Java Closures with lambda expressions.

Table Of Contents
5 Lambda Expressions
8 Arrays
10 Maps
11 Strings
25 JAXB
29 Enums
32 Audio
41 Scanner
63 Logging
75 Lists
78 Sets
89 JAX-WS
96 XJC
98 Process
106 Modules
114 Applets
122 JNDI
139 JavaBean
141 Literals
144 Packages
150 JMX
153 JShell
159 Sockets
167 Enum Map
175 Hashtable
177 SortedMap