2016-08-13 23 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中使用)。

相關問題