Java - What is the output: Functional Interfaces as Method Argument?

Question

What is the output of the following code?

public class Main {
  public static void main(String[] args) {
    LambdaUtil util = new LambdaUtil();

    util.test((x, y) -> x + y);

    util.test((x, y) -> x + y);

    util.test((x, y) -> x + " " + y);

    util.test((x, y) -> {
      StringBuilder sbx = new StringBuilder(x);
      StringBuilder sby = new StringBuilder(y);
      sby.reverse().append(",").append(sbx.reverse());
      return sby.toString();
    });
  }
}
@FunctionalInterface
interface Adder {
        double add(double n1, double n2);
}
@FunctionalInterface
interface Joiner {
        String join(String s1, String s2);
}
class LambdaUtil {
  public void test(Adder adder) {
    double x = 1.90;
    double y = 1.50;
    double sum = adder.add(x, y);
    System.out.print("Using an Adder:");
    System.out.println(x + " + " + y + " = " + sum);
  }
  public void test(Joiner joiner) {
        String s1 = "Hello";
        String s2 = "World";
        String s3 = joiner.join(s1,s2);
        System.out.print("Using a Joiner:");
        System.out.println("\"" + s1 + "\" + \"" + s2 + "\" = \"" + s3 + "\"");;
  }
}


Click to view the answer

public class Main {
  public static void main(String[] args) {
    LambdaUtil util = new LambdaUtil();

    util.test((x, y) -> x + y);//compile time error

    util.test((x, y) -> x + y);//compile time error

    util.test((x, y) -> x + " " + y);//compile time error

    util.test((x, y) -> {//compile time error
      StringBuilder sbx = new StringBuilder(x);//compile time error
      StringBuilder sby = new StringBuilder(y);//compile time error
      sby.reverse().append(",").append(sbx.reverse());
      return sby.toString();//compile time error
    });
  }
}

Note

It is not always possible for the compiler to infer the type of a lambda expression.

Sometimes, there is no way the compiler can infer the type of a lambda expression.

Reference to test() method is ambiguous.

The call to the test() method fails because the lambda expression is implicit and it matches both versions of the test() method.

You need to help the compiler by providing some more information.

The following are the some of the ways to help the compiler resolve the ambiguity:

  • If the lambda expression is implicit, make it explicit by specifying the type of the parameters.
  • Use a cast.
  • Assign lambda expression to a variable of the desired type, and then, pass the variable to the method.

The following code changes the lambda expression to an explicit lambda expression:

test((double x, double y) -> x + y); // OK. Will call test(Adder adder)

The following code uses a cast to cast the lambda expression to the type Adder:

test((Adder)(x, y) -> x + y); // OK. Will call test(Adder adder)

The following code breaks down the method call into two statements:

Adder adder = (x, y) -> x + y;
test(adder); // OK. Will call test(Adder adder)

Demo

public class Main {
  public static void main(String[] args) {
    LambdaUtil util = new LambdaUtil();

    // Calls the testAdder() method
    util.test((double x, double y) -> x + y);

    // Calls the testJoiner() method
    util.test((String x, String y) -> x + y);

    // Calls the testJoiner() method. The Joiner will
    // add a space between the two strings
    util.test((Joiner) (x, y) -> x + " " + y);

    // Calls the testJoiner() method. The Joiner will
    // reverse the strings and join resulting strings in
    // reverse order adding a comma in between
    util.test((Joiner) (x, y) -> {//  w  w w.j a v a2s .  c o  m
      StringBuilder sbx = new StringBuilder(x);
      StringBuilder sby = new StringBuilder(y);
      sby.reverse().append(",").append(sbx.reverse());
      return sby.toString();
    });
  }
}

@FunctionalInterface
interface Adder {
  double add(double n1, double n2);
}

@FunctionalInterface
interface Joiner {
  String join(String s1, String s2);
}

class LambdaUtil {
  public void test(Adder adder) {
    double x = 190.90;
    double y = 8.50;
    double sum = adder.add(x, y);
    System.out.print("Using an Adder:");
    System.out.println(x + " + " + y + " = " + sum);
  }

  public void test(Joiner joiner) {
    String s1 = "Hello";
    String s2 = "World";
    String s3 = joiner.join(s1, s2);
    System.out.print("Using a Joiner:");
    System.out.println("\"" + s1 + "\" + \"" + s2 + "\" = \"" + s3 + "\"");
    ;
  }
}

Result