Search code examples
javalambdafinaljshell

Why jshell allows non-final free variables in lambda expressions?


In a .java file, following will not compile:

class Test {
    public static void main(String[] args) {
        int x = 0;
        Runnable r = () -> System.out.println(x);
        r.run();
        x++;
        r.run();
    }
}

However in jshell, this will work and the output of the first r.run() is 0 and for the second, it is 1. So I want to know how is x accessible to r?


Solution

  • This's how jshell actually works:

    class $1 { int x; static void run() { x = 0; } }
    class $2 { Runnable r; static void run() { r = () -> print($1.x); } }
    class $3 { static void run() { $2.r.run(); } }
    class $4 { static void run() { $1.x++; } }
    class $5 { static void run() { $2.r.run(); } }
    

    Every time you enter a new command, jshell defines a new class and wraps it as a static method.

    You can see the actual class name using new Throwable().printStackTrace()