Ekaterina
Ekaterina

Reputation: 1892

Closures in Java

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

Answers (1)

kaya3
kaya3

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

Related Questions