我已经回答了很多标题相同的问题,但我没有得到我想要的答案。
在下面的Greeter
类中,有一个简单的sysout。据我所知,lambda关心的是签名(即返回类型和参数数量)。但如果我删除
int add(int a);
它非常有效,因为编译器会检查Greeting
接口中是否有任何不带参数且返回类型为void的方法。
但当我把那个方法放在那里时,我会得到主题行中提到的编译错误,根据我的理解,编译器会去Greeting
接口,它会看到有两个方法。但是,不应该有歧义,因为我的lambda表达式查找返回类型为void且只有一个参数的方法。基于这种类比,只有一种方法,因此理想情况下不应出现错误。
我知道我的类比是错误的,我知道它一定是一个函数接口,但我也认为我上面提到的过程正是编译器的工作方式。
有人能告诉我哪里错了吗?编译器在我的例子中是如何工作的?
问候界面
package lambadas;
public interface Greeting {
void perform();
int add(int a);
}
贪婪等级
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与特定方法进行匹配,而是要创建它实现的接口的有效实例。