Reputation: 1726
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");
Upvotes: 8
Views: 1598
Reputation: 200158
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.
Upvotes: 18
Reputation: 5424
Change passMeAround
to static:
public static String passMeAround( String input ) {
return input + " been passed to me";
}
or refer to it as to instance method:
public Function<String, String> testReferences() {
final Function<String, String> f1 = this::passMeAround;
return f1;
}
Upvotes: 0
Reputation: 17041
To answer your question about why the context is static, it's because the part before the ::
was the name of a class rather than the name of an instance. If you don't have an instance, only static members are accessible.
Upvotes: -1