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.
sqrt
as static, and access it asa->Fomular.sqrt(...)
– Bernettadefault
though. :) – Lippolddefault
. And if someone actually wants to accessible the method in a lambda expr, the method is very likelystatic
in nature... – Bernettadefault
and was trying to imply thatstatic
methods cannot bedefault
. – Lippoldstatic
is implicitlydefault
, as in having a method body, or, being non-abstract...) (thedefault
keyword here is more aesthetic in nature... javac didn't really need it to see that a method is non-abstract. well then,abstract
keyword wasn't needed either:) – Bernettathis
reference that could act as the receiver for the default method; the only names that are in scope are those that are in scope outside the lambda, plus the lambdas formals. If you let go of the unhelpful intuition that "lambdas are just inner classes" (which they're not), this ceases to be surprising. – Marley