Why does the following not work?
import java.util.function.Function;
public class MethodRefTest {
public String passMeAround( String input ) {
return input + " been passed to me";
}
public Function<String, String> testReferences() {
final Function<String, String> f1 = MethodRefTest::passMeAround;
return f1;
}
public static void main( String[] args ) {
new MethodRefTest()
.testReferences()
.apply( "foo" );
}
}
Javac tells me:
MethodRefTest.java:14: error: invalid method reference
final Function<String, String> f1 = MethodRefTest::passMeAround;
^
non-static method passMeAround(String) cannot be referenced from a static context
1 error
I don't understand why the context is static. I read this but it does not seem to answer the problem at hand.
Also according to oracle, "Reference to an instance method of an arbitrary object of a particular type" are possible via ContainingType::methodName
@marko-topolnik helped me understand my mistake here.
Function<String, String> f1 = MethodRefTest::passMeAround;
refers to a static method String MethodRefTest.passMeAround(String)
BiFunction<MethodRefTest, String, String> f1 = MethodRefTest::passMeAround;
on the other hand, refers to the instance method of any instance
, that is passed in the apply clause.
BiFunction<MethodRefTest, String, String> f2 = MethodRefTest::passMeAround;
//call instance method
f2.apply(new MethodRefTest(), "some string");
So the syntax for a reference to an instance method of an arbitrary object of a particular type is "ContainingType::methodName".
Summary. this Keyword in Java is a reference variable that refers to the current object. this in Java is a reference to the current object, whose method is being called upon. You can use “this” keyword to avoid naming conflicts in the method/constructor of your instance/object.
Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined by the functional interface while a method reference is similar to a lambda expression that refers a method without executing it.
Because you referred to it as
MethodRefTest::passMeAround
You should have referred to it as
this::passMeAround
providing the instance to use for context.
A different way to view your current code is to say that MethodRefTest::passMeAround
is a BiFunction<MethodRefTest, String, String>
and this lambda shape does not match the target site. So, alternatively, you may have written
public BiFunction<MethodRefTest, String, String> testReferences() {
return MethodRefTest::passMeAround;
}
and in the main method
final MethodRefTest t = new MethodRefTest();
t.testReferences().apply( t, "foo" );
The material you have been reading may not be instructive enough, so let me expand. With
this::passMeAround
you get a lambda object which has captured the this
instance from the context where it was created, but with
MethodRefTest::passMeAround
you get a "pure", non-capturing lambda which represents the invocation of the specified method on some instance, with some string argument, so when you apply
it, you need to pass in both.
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