44

I'm struggling to see why the following code compiles:

public class MethodRefs {
 public static void main(String[] args) {
 Function<MethodRefs, String> f;
 f = MethodRefs::getValueStatic;
 f = MethodRefs::getValue;
 }
 public static String getValueStatic(MethodRefs smt) {
 return smt.getValue();
 }
 public String getValue() {
 return "4";
 }
}

I can see why the first assignment is valid - getValueStatic obviously matches the specified Function type (it accepts a MethodRefs object and returns a String), but the second one baffles me - the getValue method accepts no arguments, so why is it still valid to assign it to f?

asked Apr 20, 2017 at 15:04
2

5 Answers 5

50

The second one

f = MethodRefs::getValue;

is the same as

f = (MethodRefs m) -> m.getValue();

For non-static methods there is always an implicit argument which is represented as this in the callee.

NOTE: The implementation is slightly different at the byte code level but it does the same thing.

answered Apr 20, 2017 at 15:10
Sign up to request clarification or add additional context in comments.

3 Comments

Note that the implicit argument can be made explicit (as of Java 8): public String getValue(MethodRefs this) is legal and identical to public String getValue().
@Pokechu22 I didn't know that. Is there a name for that construct?
@immibis: the spec (§8.4.1) calls it a "receiver parameter" as far as I can tell.
9

Lets flesh it out a bit:

import java.util.function.Function;
public class MethodRefs {
 public static void main(String[] args) {
 Function<MethodRefs, String> f;
 final MethodRefs ref = new MethodRefs();
 f = MethodRefs::getValueStatic;
 f.apply(ref);
 //is equivalent to 
 MethodRefs.getValueStatic(ref);
 f = MethodRefs::getValue;
 f.apply(ref);
 //is now equivalent to 
 ref.getValue();
 }
 public static String getValueStatic(MethodRefs smt) {
 return smt.getValue();
 }
 public String getValue() {
 return "4";
 }
}
answered Apr 20, 2017 at 15:12

Comments

9

A non-static method essentially takes its this reference as a special kind of argument. Normally that argument is written in a special way (before the method name, instead of within the parentheses after it), but the concept is the same. The getValue method takes a MethodRefs object (its this) and returns a string, so it's compatible with the Function<MethodRefs, String> interface.

answered Apr 20, 2017 at 15:11

Comments

6

In the Java Tutorial it is explained that there are 4 different types of method references:

  1. reference to a static method
  2. reference to an instance method of a particular object
  3. reference to an instance method of an arbitrary object of a particular type
  4. reference to a constructor

Your case is #3, meaning that when you have an instance of MethodRef i.e. ref, calling apply on your function f will be equivalent to String s = ref.getValue().

answered Apr 20, 2017 at 16:09

Comments

5

For non-static methods, the type of this is considered implicitly to be the first argument type. Since it's of type MethodRefs, the types check out.

answered Apr 20, 2017 at 15:10

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.