2

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?

Ekaterina
  • 1,642
  • 3
  • 19
  • 36

1 Answers1

4

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
Community
  • 1
  • 1
kaya3
  • 47,440
  • 4
  • 68
  • 97
  • Thank you, could you also give a reference to "synthetic final field"? โ€“ Ekaterina Dec 22 '19 at 13:58
  • 1
    Hard to get an authoritative one, since it's more like an implementation detail than a specified behaviour. The JVMS defines what "synthetic" means, but doesn't specify all cases where it applies: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.8 This article shows a decompiled lambda with a synthetic field named `cap$0`: http://www.doanduyhai.com/blog/?p=1353 The book *Java Closures and Lambda* by Robert Fischer (2015) talks about synthetic fields for lambdas on page 152. โ€“ kaya3 Dec 22 '19 at 14:14
  • 1
    I've added an example showing a synthetic field via reflection in the REPL, if that helps. โ€“ kaya3 Dec 22 '19 at 14:47