2016-08-13 100 views
2

使用JAVA8,可以用lambda表达式替换内部类。Java如何知道使用lambda表达式时应该覆盖哪种方法

Comparator c = (a, b) -> Integer.compare(a.length(), b.length()); 

Runnable java8Runner =() ->{System.out.println("I am running");}; 

jvm如何知道,这个lambda应该重写正确的方法?在上面的例子中,它们是run()compare()

+2

你的第一个例子不会编译,因为使用* raw *'Comparator'意味着编译器不知道'a'和'b'的类型是什么。将它改为'Comparator '就可以编译。 – Andreas

回答

4

Thilo是对的。

尽管如此,术语

单方法接口

不是更合适,因为一个功能接口可以具有多个方法:潜在的多个默认方法,但一个和一个抽象方法。
例如它是一个有效的功能接口:

@FunctionalInterface 
public interface MyInterface { 

    Integer getResult(); 
    default boolean isNoResult(){ 
     return getResult()==null; 
    } 
} 

表达拉姆达只能在一个功能接口的上下文中使用。 功能接口是指定一个和一个抽象方法的Java接口。 在你的例子中,Comparator和Runnable只有一个抽象方法。 更多细节在这里:https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html

如何JVM知道,这拉姆达应该重写正确的方法?在上述 示例中,它们是run()和compare()。

如果您使用无功能接口lambda表达式,编译时便会出现错误:编译器确实会抱怨它与显式消息:
这个表达式的目标类型必须是功能接口

因此,即使它不是强制性的,如果您在目标是功能接口中创建接口,最好使用注释@FunctionalInterface来声明它以强制编译器检查它是否有效功能界面:单一抽象方法。这样,当你的接口是一个功能接口有效或无效时,你现在就会知道。
这就是为什么Java 8中的JDK类会这样做。

+1

即使这不是完整的图片,一个功能接口恰好有一个'abstract'方法与'java.lang.Object'中的方法不匹配。这就是“Comparator”尽管有两个'abstract'方法是一个功能接口的原因,'boolean equals(Object)'匹配'java.lang.Object'中声明的一个方法。 – Holger

+0

准确地说,Object类的方法不被功能接口考虑 – davidxxx

7

这是通过单一方法接口的方式促进的。这些接口中只有一个(抽象)方法。如果存在歧义,则不能使用简写lambda语法。

您可以使用@FunctionalInterface注释让编译器为接口强制执行此操作(但不是必需的,即使没有它,接口也可以在lambdas中使用)。

相关问题