0

lets say we a Predicate and a Function-Interface:

Function<String, String> function = null;
Predicate<String> predicate = null;

Now I want to give the Predicate-Interface a method reference where the return type is a boolean and in our case the parameter a string. But why the following method reference seems to be right:

Predicate<String> predicate = String::isEmpty;

The isEmpty-method has no String-Parameter,although the Predicate-Interface requires a String-Parameter. Why it is still right? Am I missing something?

Another Example: The Function interface returns in our case a String and takes a String as parameter. But the following method reference seems to be wrong:

Function<String, String> function = String::concat;  //wrong

The Concat-Method has a String as Parameter and returns a String. Why its wrong?

Hopefully somebody can explain it to me.

user3133542
  • 1,695
  • 4
  • 21
  • 42
  • Your question is really about method references rather than functional interfaces. I recommend you read through https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html It explains the four types of method references and the lambda expressions they are shorthands for. – sprinter Mar 18 '17 at 22:32

3 Answers3

3

When you use a method reference on an instance method, the method receiver becomes the first argument. So

String::isEmpty

is equivalent to

(String str) -> str.isEmpty()

and

String::concat

is equivalent to

(String a, String b) -> a.concat(b)

...which does not match the type of Function.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • 1
    For completeness it might be worth adding an example of a reference to an instance method of a particular object. For example `myString::concat` is equivalent to `(String a) -> myString.concat(a)`. – sprinter Mar 18 '17 at 22:37
0

The reason why

Function<String, String> function = String::concat;

does not compile is because it is equivalent to (as Louis written)

Function<String, String> function = (String a, String b) -> a.concat(b);

while Function.apply(T t) takes only one argument (t) and you are passing a function that takes two arguments (a and b).

Adam Siemion
  • 15,569
  • 7
  • 58
  • 92
0

String::isEmpty can, in theory, mean one of two things.

  1. A static method in the String class:

    s -> String.isEmpty(s)
    
  2. An instance method in the String class:

    (String s) -> s.isEmpty()
    

Your case falls into #2.

Similarly, String::concat can mean one of two things:

    (s1, s2) -> String.concat(s1, s2)

or

    (String s1, String s2) -> s1.concat(s2) // Your case

(However, this is not a Function<String, String>, as it does not take precisely one argument. It is, however, a BinaryOperator<String>.)

Joe C
  • 15,324
  • 8
  • 38
  • 50