Java8 Lambda( -> )&&方法引用( :: )&&函式式介面(@Functional)
阿新 • • 發佈:2018-11-02
一、簡述
Java8之前建立一個執行緒的程式碼:
new Thread(new Runnable() { @Override public void run() { System.out.println("Test"); } });
其中Runnable就是一個匿名內部類,一般在一個執行緒只出現一次但必須實現。
再看Runnable的程式碼實現,就是一個Functional Interfaces函式式介面:
@FunctionalInterfacepublic interface Runnable { public abstract void run(); }
在上面的程式碼中只定義了一個抽象方法,這樣的介面,被稱為函式式介面Functional Interface;JDK裡有很多,如Predicate,Comparator。
Lambda表示式主要就是用於定義一個函式式介面的內聯實現,如 Runnable r = ()-> System.out.println("Test"); ,我們用Lambda表示式實現了Runnable介面。
所以建立執行緒可以簡寫成 new Thread(()->System.out.println("Test")) 。
至於方法引用,他只是一種更簡單的lambda表示式,提供了一種引用而不執方法的方式。
String::valueOf 等價於lambda表示式 (s) -> String.valueOf(s)
Lambda,Functional Interface,MethodReference,也有很多規則和約束。
二、規則
1、Lambda
Lambda表示式具有如下特徵:
- 【可選】型別宣告:引數的型別不需要宣告,編譯器可以根據引數值推斷出其型別;
- 【可選】括號:單個引數的話,不需要用圓括號包圍引數,當然,對於多個引數或無引數的話,括號是需要的;
- 【可選】花括號:如果表示式主體只有一條語句的話,不需要用花括號包圍,當然,對於多條語句,花括號是需要的;
- 【可選】return關鍵字:如果表示式主體是單一表達式,return關鍵字可以不寫,編譯器可以自動返回該值,當然,如果寫了return,則需要加上花括號;
2、函式式介面
- 只能有一個抽象方法。
- @FunctionalInterface,主要用於編譯級錯誤檢查,當你寫的介面不符合函式式介面定義的時候,編譯器會報錯,加不加@FunctionalInterface對於介面是不是函式式介面沒有影響
- 可以包含預設方法,因為預設方法不是抽象方法,其有一個預設實現,所以是符合函式式介面的定義的;default關鍵字
- 可以包含靜態方法,因為靜態方法不能是抽象方法,是一個已經實現了的方法,所以是符合函式式介面的定義的;
- 可以包含Object裡的public方法,這些方法對於函式式介面來說,不被當成是抽象方法(雖然它們是抽象方法);因為任何一個函式式介面的實現,預設都繼承了Object類,包含了來自java.lang.Object裡對這些抽象方法的實現;
3、方法引用
四種方法引用型別
型別 | 示例 |
引用靜態方法 | ContainingClass::staticMethodName |
引用某個物件的例項方法 | containingObject::instanceMethodName |
引用某個型別的任意物件的例項方法 | ContainingType::methodName |
引用構造方法 | ClassName::new |
a、靜態方法引用
就是靜態方法可以用
b、特定物件例項方法
Student s = new Student() Arrays.sort(students,s::getAge)
super::methodName
this :: equals
c、任意物件的例項方法引用
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
d、構造方法引用
String::new, 等價於lambda表示式 () -> new String() int[]::new 是一個含有一個引數的構造器引用,這個引數就是陣列的長度。等價於lambda表示式 x -> new int[x]