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