Forward reference from lambda expression in field initializer

Markus Keller markus_keller at ch.ibm.com
Wed Dec 18 10:07:19 PST 2013


Dan Smith <daniel.smith at oracle.com> wrote on 2013-12-17 23:27:01:
> 3 Dec 2013, Markus Keller <markus_keller at ch.ibm.com>, "Self-reference to 
field from lambda expression in initializer"
> I've had quite a few discussions about this, and concluded that it is 
best not to do anything until we flesh out a potential "recursive lambda 
expression" feature in the future.

Sorry, the subject of my mail was misleading. I agree with not adding a 
way to refer to a lambda's "this".

> (In 8, local variables initialized with lambdas have a similar inability 
to directly refer to themselves.)

That restriction for local variables is not new in 8 and isn't exclusive 
to lambdas:

    static void post(Runnable r) { }
    void foo() {
        Runnable r1 = r1; // error: r1 not initialized
        Runnable r2 = () -> post(r2); // error: r2 not initialized
        Runnable r3 = new Runnable() {
            @Override
            public void run() {
                post(r3); // error: r3 not initialized
            }
        };
    }


The problem is actually not only about self-references from the lambda 
body of a field initializer, but about any forward reference that is 
forbidden by JLS7 8.3.2.3.

A better example:
----------
public class D {
    int v1 = value; // Error for 8.3.2.3 (good).
    int v2 = D.this.value; // No simple name -> no error (good).
 
    IntSupplier s1 = () -> value; // Why error?
    IntSupplier s2 = new IntSupplier() {
        @Override
        public int getAsInt() {
            return value; // No error (good).
        }
    };
 
    int value = 42;
}
----------

There's absolutely no problem with the reference in s1's initializer. The 
only problem is that 8.3.2.3 needs to be updated to make lambda bodies 
behave the same as nested class bodies.

REQUEST:
========
8.3.2.3 should get a fifth point:
"- The usage is not in a lambda expression body that occurs inside c."

The next sentence could also be clarified to:
"It is a compile-time error if any of the five requirements above are not 
met for such a forward reference.
========

FWIW, this still excludes the forward reference to "VALUE" here:

    public static final IntConsumer c = (@A(VALUE) int x) -> {};
    public static final int VALUE = 42;


Markus



More information about the lambda-spec-observers mailing list