Why can we not use default methods in lambda expressions?

codegasmer picture codegasmer · Oct 13, 2015 · Viewed 10.4k times · Source

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.

Answer

Sotirios Delimanolis picture Sotirios Delimanolis · Oct 13, 2015

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.