Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 444
user Avatar asked Jul 02 '17 20:07

user


People also ask

Can be replaced with method reference lambda?

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.

Is method reference only for functional interface?

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.

When can we use 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.

What is the benefit of method reference?

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.


1 Answers

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

like image 79
davidxxx Avatar answered Oct 06 '22 23:10

davidxxx