Consider the following examples
Consumer<Long> f1 = new Consumer<>() {
@Override
public void accept(Long value) {
if (value < 5) {
this.accept(value + 1); //this refers to the anonymous context.
}
}
}
Consumer<Long> f2 = (value) -> {
if (value < 5) {
this.accept(value + 1); //this refers to outer context and the anonymous function is not referable.
}
};
It is seen that this
is not provided for the lambda f2
but is given for the more explicitly written anonymous Consumer implementation f1
.
Why is this so? What would be the language design difficulty in providing this
for the lambda body?
The Java Language Specification 15.27.2 says:
Unlike code appearing in anonymous class declarations, the meaning of names and the
this
andsuper
keywords appearing in a lambda body, along with the accessibility of referenced declarations, are the same as in the surrounding context (except that lambda parameters introduce new names).The transparency of
this
(both explicit and implicit) in the body of a lambda expression - that is, treating it the same as in the surrounding context - allows more flexibility for implementations, and prevents the meaning of unqualified names in the body from being dependent on overload resolution.Practically speaking, it is unusual for a lambda expression to need to talk about itself (either to call itself recursively or to invoke its other methods), while it is more common to want to use names to refer to things in the enclosing class that would otherwise be shadowed (
this
,toString()
). If it is necessary for a lambda expression to refer to itself (as if viathis
), a method reference or an anonymous inner class should be used instead.