That's not exactly true. Default methods can be used in lambda expressions.
interface Value {
int get();
default int getDouble() {
return get() * 2;
}
}
public static void main(String[] args) {
List<Value> list = Arrays.asList(
() -> 1,
() -> 2
);
int maxDoubled = list.stream()
.mapToInt(val -> val.getDouble())
.max()
.orElse(0);
System.out.println(maxDoubled);
}
prints 4
as expected and uses a default method inside a lambda expression (.mapToInt(val -> val.getDouble())
)
What the author of your article tries to do here
Formula formula = (a) -> sqrt( a * 100);
is to define a Formula
, which works as functional interface, directly via a lambda expression.
That works fine, in above example code, Value value = () -> 5
or with Formula
as interface for example
Formula formula = (a) -> 2 * a * a + 1;
But
Formula formula = (a) -> sqrt( a * 100);
fails because it's trying to access the (this.
)sqrt
method but it can't.
Lambdas as per spec inherit their scope from their surroundings, meaning that this
inside a lambda refers to the same thing as directly outside of it. And there is no sqrt
method outside.
My personal explanation for this: Inside the lambda expression, it's not really clear to what concrete functional interface the lambda is going to be "converted". Compare
interface NotRunnable {
void notRun();
}
private final Runnable r = () -> {
System.out.println("Hello");
};
private final NotRunnable r2 = r::run;
The very same lambda expression can be "cast" to multiple types. I think of it as if a lambda doesn't have a type. It's a special typeless function that can be used for any Interface with the right parameters. But that restriction means that you can't use methods of the future type because you can't know it.