Always when I use lambda expressions like this:
.map(obj -> foo.makeSomething(obj))
IntelliJ suggests: "Can be replaced with method reference...". And when I try then:
.map(Foo::makeSomething)
I get the following statement: "Non-static method cannot be referenced from a static context".
Why Idea suggests me I should use method reference if it's not correct?
If you are using a lambda expression as an anonymous function but not doing anything with the argument passed, you can replace lambda expression with method reference. In the first two cases, the method reference is equivalent to lambda expression that supplies the parameters of the method e.g. System.
Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.
The method references can only be used to replace a single method of the lambda expression. A code is more clear and short if one uses a lambda expression rather than using an anonymous class and one can use method reference rather than using a single function lambda expression to achieve the same.
The biggest benefit of the method reference or constructor reference is that they make the code even shorter by eliminating lambda expression, which makes the code more readable.
As you write :
map(Foo::makeSomething)
the compiler expects one of these two possibilities :
invoking a Foo.makeSomething()
instance method on the first parameter of the lambda that has to be so defined as a Foo
.
invoking a Foo.makeSomething()
static method.
The first possibility is eliminated by the compiler as the first parameter of the lambda declared obj
is not a Foo
.
And according to your error message, Foo.makeSomething()
is an instance method :
Non-static method cannot be referenced from a static context"
So, the second possibility (invoking a Foo.makeSomething()
static method) is not legal either as makeSomething()
is not static.
In fact, what you want is applying the makeSomething()
instance method on a variable that doesn't make part of the lambda parameters.
You can do it but you need to use another syntax.
Instead of specifying Foo::
, use foo::
.
In this way, the instance method makeSomething()
will be applied on the foo
variable :
map(foo::makeSomething)
IntelliJ Intention
Note that inspection that reports lambdas which can be replaced with method references can also be automatically refactored by the IDE via an intention.
To do that, set the cursor on the lambda (anywhere on it) and display contextual intentions (Alt+Enter
by default). You should see the intention :
Replace lambda with method reference
Some screenshots :
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With