Code in lambdas and anonymous classes handled differently
Unlike the code that appears in anonymous class declarations, the meaning of the this and super names and keywords included in the lambda body, as well as the availability of link declarations, are the same as in the surrounding context (except that the lambda parameters introduce new names) .
The transparency of this (both explicit and implicit) in the body of the lambda expression - that is, considering it in the same way as in the surrounding context - provides greater flexibility for implementations and prevents meaning unqualified names in the body depend on overload resolution. In fact, itโs unusual that a lambda expression has to talk about itself (either call itself recursively or refer to other methods), while the more common desire is to use names to indicate things in the covering class that would otherwise obscure (this, toString () ) If you want the lambda expression to refer to itself (as if through this ), you should instead use a reference to a method or an anonymous inner class.
JLS 10 - 15.27.2. Lambda body
Code in lambdas
The this can be used in a lambda expression only if it is allowed in the context in which the lambda expression appears. Otherwise, a compile-time error occurs.
JLS 10 - 15.8.3. this
I think it can also be applied to the super keyword.
Operator A.super.doA(); will work in an encompassing context (the body of the Test#doA ), so it is also allowed in lambdas.
class Test implements A { @Override public void doA() { B b = () -> { System.out.println(super.getClass()); System.out.println(Arrays.toString(super.getClass().getInterfaces())); }; b.doB();
This snippet prints.
class Test [interface A]
We compare it with the anonymous class result.
Code in Anonymous Classes
class Test implements A { @Override public void doA() {
Fragmentation
class Test$1 [interface B]
Remembering that the anonymous class has its own this and super , and it does not inherit A (and cannot do this), it becomes clear that A.super.doA(); cannot be compiled into its context.
Bypass
A workaround is to remember the storage context with a lambda and call that lambda in an anonymous class method:
class Test implements A { @Override public void doA() { Runnable doA = () -> A.super.doA(); new B() { public void doB() { doA.run(); } }.doB(); } }
If B inherits A , one could call doA() or B.super.doA() , invoking the default method:
class Test implements A { @Override public void doA() { new B() { public void doB() { doA();