Given this:
class MyClass {
static class A {
public boolean property() {
return Math.random() < 0.5;
}
}
static List<A> filterLambda(List<A> list) {
return list.stream().filter(a -> a.property()).collect(Collectors.toList());
}
static List<A> filterMethodCall(List<A> list) {
return list.stream().filter(A::property).collect(Collectors.toList());
}
}
- What are the differences in what the compiler does for each method?
- In case there's any, is there a difference in memory usage or runtime? (even if it's small, the question is just academic)
PD: I know the question is similar to this one but I think it's not been addressed correctly.
This is an extract from the Brian Goetz's doc linked by Brett Oken:
Examples extracted from same doc:
As an example, consider a lambda that captures a field minSize:
We desugar this as an instance method, and pass the receiver as the first captured argument:
While
is translated as:
One case where we can find the difference lambda expression & method reference is using as part of Supplier interface. Lets say we have below static method
When we call the method using lambda expression as below, code work fine since the lambda expression passed as part of Supplier & executed only when get() method is called where the exception is caught.
When we call the method using method reference as below, we get NullPointerExecption before calling the method since the reference is executed before passing in to the supplier. The control does not reach get() method in this case.
Here is the java language spec on method references.
Here is the spec for lambda expressions.
Lambdas are quite a bit more complex from a rules perspective.
In both cases, however, the result is an invokedynamic call.
Brian Goetz has written a doc on how this works.