目标类型的表达式必须是一个功能接口 - 为什么需要它?

时间:2017-10-31 11:22:07

标签: java lambda compiler-errors java-8 functional-interface

我经历了很多具有相同标题的问题,但我没有得到我想要的答案。

在下面的Greeter课程中,有一个简单的sysout。据我了解,lambda关心的是签名(即返回类型和参数号)。但如果我删除

  

int add(int a);

它完美有效,因为编译器会检查Greeting接口中是否有任何可用的方法,它没有参数且返回类型为void。

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

我知道我的比喻在这里是错误的,我知道它必须是一个功能界面,但我也认为我上面提到的过程正是编译器的工作方式。

任何人都可以让我知道我错在哪里以及编译器在我的例子中是如何工作的吗?

问候语界面

package lambadas;

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

Greeter 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;
    }

}

2 个答案:

答案 0 :(得分:5)

使用@FunctionalInterface注释您的界面 - 并看到它破裂。只允许使用单个抽象方法。

答案 1 :(得分:3)

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

通过将功能接口强制为lambda表达式的目标类型,编译器可以保证您不会对这些接口进行部分实现。这与HelloWorldGreeting未实现add(int)时可能遇到的编译器错误的原因完全相同:您提供了1个实现,但有两种方法可以实现。

所以这不是关于将lambda与特定方法匹配,而是关于创建它实现的接口的有效实例。