Search code examples
javalambdainterfacejava-8default-method

Why can we not use default methods in lambda expressions?


I was reading this tutorial on Java 8 where the writer showed the code:

interface Formula {
    double calculate(int a);

    default double sqrt(int a) {
        return Math.sqrt(a);
    }
}

And then said

Default methods cannot be accessed from within lambda expressions. The following code does not compile:

Formula formula = (a) -> sqrt( a * 100);

But he did not explain why it is not possible. I ran the code, and it gave an error,

incompatible types: Formula is not a functional interface`

So why is it not possible or what is the meaning of the error? The interface fulfills the requirement of a functional interface having one abstract method.


Solution

  • It's more or less a question of scope. From the JLS

    Unlike code appearing in anonymous class declarations, the meaning of names and the this and super 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).

    In your attempted example

    Formula formula = (a) -> sqrt( a * 100);
    

    the scope does not contain a declaration for the name sqrt.

    This is also hinted at in the JLS

    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 via this), a method reference or an anonymous inner class should be used instead.

    I think it could have been implemented. They chose not to allow it.