Intellij - can be replaced with method reference

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?

65713 次浏览

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 :

intention proposition

intention result