Java Lambda Behaviour Parameter








We can pass lambda expressions to methods as arguments.

Example

The following code creates a functional interface called Calculator.

Inside the Calculator there is a method called calculate which accepts two int parameters and return an int value.

In the Main class there is an engine method which accepts the functional interface Calculator as the parameter. And it calls the calculate method from the Calculator and outputs the result.

In the main method we call the engine methods four times with different lambda expressions.

public class Main {
  public static void main(String[] argv) {
    engine((x,y)-> x + y);// w w  w .j  av a 2s.  c om
    engine((x,y)-> x * y);
    engine((x,y)-> x / y);
    engine((x,y)-> x % y);
  }
  private static void engine(Calculator calculator){
    int x = 2, y = 4;
    int result = calculator.calculate(x,y);
    System.out.println(result);
  }
}

@FunctionalInterface
interface Calculator{
  int calculate(int x, int y);
}

The code above generates the following result.





Note

The result of engine method is depending on lambda expressions passed into it.

The behaviour of engine method is parameterized.

Changing the behavior of a method through its parameters is called behavior parameterization.

In behavior parameterization we pass logic encapsulated in lambda expressions to methods as if was data.

Behavior parameterization Ambiguity

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

One such situation is passing lambda expressions to overloaded methods.

There are two functional interfaces in the following code. One is for int value calculation and the other is for long value.

In the Main class there are overloaded methods called engine. One is expecting IntCalculator and another is for LongCalculator.

In the main method we have to indicate the parameters for lambda expression to indicate compiler which overloaded function we want to use.

public class Main {
  public static void main(String[] argv) {
    engine((int x,int y)-> x + y);
    engine((long x, long y)-> x * y);
    engine((int x,int y)-> x / y);
    engine((long x,long y)-> x % y);
  }/*  w ww  .  java 2 s . com*/
  private static void engine(IntCalculator calculator){
    int x = 2, y = 4;
    int result = calculator.calculate(x,y);
    System.out.println(result);
  }
  private static void engine(LongCalculator calculator){
    long x = 2, y = 4;
    long result = calculator.calculate(x,y);
    System.out.println(result);
  }  
}

@FunctionalInterface
interface IntCalculator{
  int calculate(int x, int y);
}

@FunctionalInterface
interface LongCalculator{
  long calculate(long x, long y);
}

The code above generates the following result.





Note 1

To resolve the ambiguity we can change the implicit lambda expression to explicit by specifying the type of the parameters. This is what has been done for the code above.

Or we can use a cast as follows. When calling the engine the first time we cast the lambda expression to IntCalculator.

public class Main {
  public static void main(String[] argv) {
    engine((IntCalculator) ((x,y)-> x + y));
    engine((long x, long y)-> x * y);
    engine((int x,int y)-> x / y);
    engine((long x,long y)-> x % y);
  }/*  w  w  w .  java 2 s .c  o m*/
  private static void engine(IntCalculator calculator){
    int x = 2, y = 4;
    int result = calculator.calculate(x,y);
    System.out.println(result);
  }
  private static void engine(LongCalculator calculator){
    long x = 2, y = 4;
    long result = calculator.calculate(x,y);
    System.out.println(result);
  }  
}

@FunctionalInterface
interface IntCalculator{
  int calculate(int x, int y);
}

@FunctionalInterface
interface LongCalculator{
  long calculate(long x, long y);
}

The code above generates the following result.

Note 2

Or we can avoid using the lambda expression directly as the parameter. We can assign the lambda expression to a functional interface, and then pass the variable to the method. The following code shows this technique.

public class Main {
  public static void main(String[] argv) {
    IntCalculator iCal = (x,y)-> x + y;
    engine(iCal);/*from  www  .java2s . c om*/
    engine((long x, long y)-> x * y);
    engine((int x,int y)-> x / y);
    engine((long x,long y)-> x % y);
  }
  private static void engine(IntCalculator calculator){
    int x = 2, y = 4;
    int result = calculator.calculate(x,y);
    System.out.println(result);
  }
  private static void engine(LongCalculator calculator){
    long x = 2, y = 4;
    long result = calculator.calculate(x,y);
    System.out.println(result);
  }  
}

@FunctionalInterface
interface IntCalculator{
  int calculate(int x, int y);
}

@FunctionalInterface
interface LongCalculator{
  long calculate(long x, long y);
}

The code above generates the following result.