I am trying to understand the Consumer interface of Java. I have replicated it. But it throws StackOverflowError when i replace the lambda expression in return statement of andThen() method with anonymous class definition:
interface Interface<T> {
void accept(T t);
default Interface<T> andThen(Interface<T> after) {
//return (T t)->{accept(t); after.accept(t);};//this runs correctly
//below is the anonymous class definition of above lambda expression
return new Interface<T>(){
@Override
public void accept(T t)
{
accept(t); //stackoverflow error thrown
after.accept(t);
}
};
}
}
//Main class:
public class Lambda2 {
public static void main(String args[]) {
Interface<String> e1=str -> System.out.println("in e1 - "+str);
Interface<String> e2=str -> System.out.println("in e2 - "+str);
Interface<String> e3 = e1.andThen(e2);
e3.accept("Sample Output");
}
}
Could you please let me know why the lambda expression of the anonymous class definition does not cause StackOverflowError?
You can find the reason for this in JLS 15.27.2 (my emphasis):
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).
That is, the name accept
inside the lambda body has the same meaning as the accept
outside the lambda body; and the difference is an anonymous class is explicitly called out.
So: calling accept
in a lambda defined the body of the andThen
method will involve the accept
method on the instance (just as if you had invoked accept
directly in the method body); whereas calling accept
in the body of the accept
method in the anonymous class will recursively invoke itself.