Reputation: 1892
This example is a simulation of closures in JavaScript (I don't know JS):
public class Lambda {
public static void main(String[] args) {
Supplier generator = Lambda.generator();
System.out.println(generator.get());
System.out.println(generator.get());
System.out.println(generator.get());
}
static Supplier<Integer> generator() {
Integer arr[] = {0};
return () -> ++arr[0];
}
}
The output is 1 2 3.
Usually the lifespan of local method variables is limited by the method execution time. But in this case the reference to arr[]
is stored somewhere. So where is it stored and what's under the hood?
Upvotes: 2
Views: 152
Reputation: 51034
The Java Language Specification (§15.27.4) says:
The value of a lambda expression is a reference to an instance of a class with the following properties:
- The class implements the targeted functional interface type ...
So the lambda defines a class, much like an anonymous class declaration does, and the lambda expression results in a reference to an instance of that class. The reference to arr
is held by a synthetic final
field belonging to that instance.
Here's an example using reflection in the JShell REPL, to demonstrate a lambda with a synthetic field:
> class A { static Runnable a(int x) { return () -> System.out.println(x); } }
| created class A
> Runnable r = A.a(5);
r ==> A$$Lambda$15/1476394199@31ef45e3
> import java.lang.reflect.Field;
> Field f = r.getClass().getDeclaredFields()[0];
f ==> private final int A$$Lambda$15/1476394199.arg$1
> f.setAccessible(true);
> f.get(r)
$6 ==> 5
Upvotes: 4