Search code examples
javalambdajava-8overridingfunctional-interface

Java method can't be applied with Lambda expression


I've watched and read https://caveofprogramming.com/java/whats-new-in-java-8-lambda-expressions.html and I follow the same pattern I did for runner object which works fine.

Runner runner = new Runner();
runner.run(() -> System.out.println("Print from Lambda expression"));

Then, I try to create a simple interface and class to apply what I learned. I just want to replace the anonymous class with a lambda expression. My understanding is a lambda expression is a shorter code for the anonymous class and improve readability.

So, I tried to initiate another instance called eucalyptus1 and try to @Override the grow() method, but my IDE error message said:

grow() in com.smith.Eucalyptus cannot be applied to (lambda expression)

Could anyone point me out what I misunderstand here?

The code is below:

// a simple interface
interface Plant {
    public void grow();
}

// apply interface to class
class Eucalyptus implements Plant {
    @Override
    public void grow() {
        System.out.println("This is from Eucalyptus");
    }
}

public class Main {
    public static void main(String[] args) {

        // Create an instance of Eucalyptus
        Eucalyptus eucalyptus = new Eucalyptus();
        eucalyptus.grow();

        // Anonymous class Myrtle from Plant interface
        Plant myrtle = new Plant() {
            @Override
            public void grow() {
                System.out.println("This was running from anonymous class from Plant Interface");
            }
        };

        myrtle.grow();

        // Try to create a lambda expression from Plant interface
        // and override grow() method
        // by print ("This was running from Lambda expression")

        // this won't work. why?
        Eucalyptus eucalyptus1 = new Eucalyptus();
        eucalyptus1.grow(() -> System.out.println("This from Lambda expression"));
    }
}

Solution

  • The difference there is that you're trying to override the implementation of Eucalyptus which is a class that implement the interface.

    Eucalyptus eucalyptus1 = new Eucalyptus();
    eucalyptus1.grow(() -> System.out.println("This from Lambda expression")); 
    ^__  // you cannot override a method using an instance of a class which is just an implementation of the interface
    

    All you end up doing there is pass a lambda parameter and of course, a method without arguments in its definition wouldn't compile if supplied with one at the time of method call.


    Instead, you can compare the way of implementing the lambda as :

    //Anonymous class Myrtle from Plant interface
    Plant myrtle = new Plant() {
              @Override
              public void grow() {
                   System.out.println("This was running from anonymous class from Plant Interface");
              }
    };
    myrtle.grow();
    

    can be represented as a lambda representation:

    Plant lambdaRep =  () -> System.out.println("This is running via lambda from Plant Interface");
    lambdaRep.grow();