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

Java method can't be applied with Lambda expression

我看过并阅读了 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"));

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

因此,我尝试启动另一个名为 eucalyptus1 的实例并尝试 @Override grow() 方法,但我的 IDE 错误消息说:

grow() in com.smith.Eucalyptus cannot be applied to (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"));
    }
}

区别在于您试图覆盖 Eucalyptus 的实现,后者是实现接口的 class。

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

你最终要做的就是传递一个 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();

可以表示为lambda表示法:

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

问题

方法grow没有接受任何参数,所以你得到了编译错误。

解释

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

Plant plant = () -> System.out.println("This from Lambda expression");

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

这里有点误会。 lambda 不应该覆盖方法,它取决于提供基于@FunctionalInterface 类型的方法


*如果您要通过 lambda 定义一个 Eucalyptus 对象,那么 lambda 代表什么方法将是模棱两可和不清楚的。因此,禁止

此处您对 lambda 表达式的使用不正确。

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

这里是正常使用:

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

换句话说,因为你有一个功能接口,你应该能够避免创建 classes 实现它(匿名或非匿名)。

因此您根本不需要创建 Eucalyptus class。