像上幾章提到的,函式式介面定義且只定義了一個抽象方法。函式式介面很有用,因為抽象方法的簽名可以描述Lambda表示式的簽名。函式式介面的抽象方法的簽名成為函式描述符。所以為了應用不同的Lambda表示式,你需要一套能夠描述常見函式描述符的函式式介面。Java API中已經有了幾個函式式介面,比如之前幾章提到的Comparator,Runnable和Callable。
Java8的庫設計師幫你在java。util。function包中引入了幾個新的函式式介面。我們接下來會介紹Predicate,Consumer和Function。
Predicate
java。util。function。Predicate
@FunctionalInterfacepublic interface Predicate 如果你去查Predicate介面的Javadoc說明,可能會注意到諸如and和or等其他方法。現在你不用太計較這些,我們會在後面討論。 Consumer java。util。function。Consumer @FunctionalalInterfacepublic interface Consumer Function java。util。function。Function @FunctionalInterfacepublic interface Function 原始型別特化 我們介紹了三個泛型函式式介面:Predicate 回顧一下:Java型別要麼是引用型別(比如Byte,Integer,Object,List),要麼是原始型別(int,double,byte,char)。但是泛型(比如Consumer List 但這在效能方面是要付出代價的。裝箱後的值本質就是把原始型別包裹起來,並儲存在堆裡面。因此,裝箱後的值需要更多的記憶體,並需要額外的記憶體搜尋來獲取被包裹餓的原始值。 Java 8為我們前面說的函式式介面帶來一個專門的版本,以便在輸入和輸出都是原始型別時避免自動裝箱的操作。比如,在下面的程式碼中,使用IntPredicate就避免了對值1000進行裝箱操作,但要是用Predicate public interface IntPredicate{ boolean test(int t);}IntPredicate evenNumbers = (int i) -> i % 2 == 0;evenNumbers。test(1000);Predicate 一般來說,針對專門的輸入引數型別的函式式介面的名稱都要加上對應的原始型別字首,比如D歐巴了 Predicate,IntConsumer,LongBinaryOperator等。Function介面還有針對輸出引數的變種:ToIntFunction 為了總結關於函式式介面和Lambda的討論,下面總結了一些使用案例、Lambda的例子,以及可以使用的函式式介面。 請注意,任何函式式介面都不允許丟擲受檢異常。如果你需要Lambda表示式來丟擲異常,有兩種方法:定義一個自己的函式式介面,並且宣告受檢異常,或者把Lambda包在一個try/catch塊中。 現在你知道如何建立Lambda,在哪裡以及如何使用他們了。後面的章節我們會介紹一些更高階的細節:編譯器如何對Lambda做型別檢查,以及你應當瞭解的規則,諸如Lambda在自身內部引用區域性變數,還有和void相容的Lambda等。