表达式的目标类型必须是函数式接口——为什么需要这个?

The target type of expression must be a functional interface – why is this needed?

我已经回答了很多标题相同的问题,但我没有得到我正在寻找的答案。

Greeter class下面有一个简单的sysout。据我了解,lambda 关心的是签名(即 return 类型和参数数量)。但是如果我删除

int add(int a);

它完美地工作,因为编译器将检查 Greeting 接口中是否有任何可用的方法,该方法没有参数且 return 类型为 void。

但是当我保留那个方法时,我得到了主题行中提到的编译错误,根据我的理解,编译器将转到 Greeting 接口,它会看到有两个方法。但是应该没有歧义,因为我的 lambda 表达式查找 return 类型为 void 且只有一个参数的方法。基于这个类比,只有一种方法,所以理想情况下它不应该出错。

我知道我的类比在这里是错误的,我知道它一定是一个功能接口,但我也认为我上面提到的过程正是编译器将如何工作。

任何人都可以让我知道我错在哪里以及编译器在我的示例中的实际工作方式吗?

问候界面

package lambadas;

public interface Greeting {
    void perform();
    int add(int a);
}

迎宾员class

package lambadas;

public class Greeter {

    public static void main(String[] args) {
        Greeting l = () -> System.out.println("hello");
        l.perform();
    }
}

HelloWorldGreeting

package lambadas;

public class HelloWorldGreeting implements Greeting {

    @Override
    public void perform() {
        System.out.println("hello world.!");
    }
    @Override
    public int add(int a) {
      return 0;
    }

}

@FunctionalInterface 注释您的界面 - 看看它是否会崩溃。只允许 单个 抽象方法。

首先问自己这个问题:如果可以这样实现 Greeting,调用 l.add(0) 时会发生什么? NoSuchMethodError?未定义的行为?你可能不想要那个——语言设计者也不想要它。

通过强制将函数接口作为 lambda 表达式的目标类型,编译器保证您没有这些接口的部分实现。如果 HelloWorldGreeting 也没有实现 add(int),这与编译器错误的原因完全相同:您提供了 1 个实现,但是有 2 个方法要实现。

因此,这并不是真正将您的 lambda 与特定方法相匹配,而是创建其实现的接口的有效实例。