Search code examples
java-8functional-interface

How java 8 evaluates internally when passing "pass a reference" to a method that matches the parameter list of abstract method?


I have been working with java 8 functional interfaces and I noticed something unusual when I started executing below code.

interface Carnivore{

  default int calories( List<String> food)
  {
     System.out.println("=======line ABC ");
     return food.size() * 100;
  }

   int eat(List<String> foods);

}

class Tiger implements Carnivore{

   public int eat(List<String> foods)
   {
     System.out.println("eating  "+ foods);

     return foods.size();
   }
}   


public class TestClass {

  public static int size(List<String> names){
     System.out.println("======line XYZ ");
     return names.size()*2;
  }
  public static void process(List<String> names, Carnivore c){
     c.eat(names);
  }


  public static void main(String[] args) {

    List<String> fnames =   Arrays.asList("a", "b", "c");

    Tiger t = new Tiger();

    process(fnames, t::eat);
    process(fnames, t::calories);
    process(fnames, TestClass::size ); // ----> this is where I am confused.  
  }
}

As you can see that static method process(List<String> names, Carnivore c) takes object type Carnivore. The method call process(fnames, TestClass::size ) works, and there's no compile time error, how is this possible? I'm not able to comprehend how internally this method call works. I was expecting an error because TestClass is not Carnivore.

The best answer I found: "You can either pass a Carnivore instance explicitly or pass a reference to a method that matches the parameter list of Carnivore's abstract method eat(List<String> foods)"

The part pass a reference to a method that matches the parameter list of abstract method is confusing to me.

Appreciated if experts help me understand what happens when process(fnames, TestClass::size ); is called.


Solution

  • Carnivore is a functional interface having a single abstract method int eat(List<String> foods);.

    Therefore, any method that fits the signature of the eat method can be used to implement the interface.

    public static int size(List<String> names) is such a method, since it takes a List<String> argument and returns an int. Therefore TestClass::size can be passed as an argument of type Carnivore, which is why process(fnames, TestClass::size); passes compilation.

    BTW, Tiger does not have to implement the Carnivore interface for process(fnames, t::eat); to pass compilation, since the public int eat(List<String> foods) method also matches the signature of the functional interface's single abstract method.