Java方法不能与Lambda表达式一起应用

Smi*_* Lo 11 java lambda overriding java-8 functional-interface

我已经观看并阅读了https://caveofprogramming.com/java/whats-new-in-java-8-lambda-expressions.html并且我遵循了我为跑步者对象所做的相同模式.

Runner runner = new Runner();
runner.run(() -> System.out.println("Print from Lambda expression"));
Run Code Online (Sandbox Code Playgroud)

然后,我尝试创建一个简单的接口和类来应用我学到的东西.我只想用lambda表达式替换匿名类.我的理解是lambda表达式是匿名类的较短代码并提高了可读性.

所以,我试图启动另一个实例调用eucalyptus1并尝试@Overridegrow()方法,但我的IDE错误消息说:

grow()com.smith.Eucalyptus无法应用(lambda expression)

有人能指出我在这里误解了什么吗?

代码如下:

// 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"));
    }
}
Run Code Online (Sandbox Code Playgroud)

Nam*_*man 10

不同之处在于,您试图覆盖Eucalyptus实现接口的类的实现.

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
Run Code Online (Sandbox Code Playgroud)

你最后做的就是传递一个lambda参数,当然,如果在方法调用时提供了一个参数,那么它的定义中没有参数的方法将无法编译.


相反,您可以将实现lambda的方式进行比较:

//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();
Run Code Online (Sandbox Code Playgroud)

可以表示为lambda表示:

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


And*_*lko 10

问题

该方法grow不带任何参数,因此您得到了编译错误.

说明

lambda () -> System.out.println("This from Lambda expression")本身可以表示Plant(而不是Eucalyptus*)实例:

Plant plant = () -> System.out.println("This from Lambda expression");
Run Code Online (Sandbox Code Playgroud)

尝试从Plant接口创建lambda表达式并通过print 创建覆盖grow()方法"This was running from Lambda expression".

这里有一点误会.lambda不应该覆盖一个方法,它要提供一个基于@FunctionalInterface类型的方法.


*如果你Eucalyptus要用lambda 定义一个对象,那将是不明确的并且不清楚lambda将代表什么方法.因此,它被禁止(即使对于使用单一抽象方法的抽象类.)


ern*_*t_k 7

你在这里使用lambda表达式是不正确的.

您使用lambda表达式来实现接口.在这种情况下,您将提供Plant使用lambda表达式的实现,而不是使用lambda表达式调用该接口的方法:

这是正常使用:

Plant eucalyptus1 = () -> System.out.println("This from Lambda expression");
eucalyptus1.grow(); // Prints "This from Lambda expression"
Run Code Online (Sandbox Code Playgroud)

换句话说,因为你有一个功能界面,你应该能够避免创建实现它的类(匿名与否).

所以你根本不需要创建Eucalyptus类.