Lambda表達式是java Stream的使用基礎。
lambda表達式的語法由參數列表、->和函數體組成。函數體既可以是一個表達式,也可以是一個語句塊。表達式執行后會返回執行結果。語句塊中使用return將控制權轉給調用者。表達式函數體省略return,適用於小型表達式,使得語法更加簡潔。
參數可以無參或多個參數,參數可以指定數據類型,參數放在()中,無參的情況下()中為空,單參可以不用();函數體可以為表達式或語句塊,單個表達式也可以放在語句塊中。
接口:
1 public interface OnClickListener { 2 void doOnClick(); 3 }
無參Lambda表達式:
1 OnClickListener mListener = () -> System.out.println("do on Click"); 2 或 3 OnClickListener mListener_ = () -> { 4 System.out.println("插上電源"); 5 System.out.println("打開電視"); 6 };
單個參數的情況下,可以省略(),多參數的情況不可以省略。
1 OnItemClickListener mItemListener = position -> System.out.println("position = [" + position + "]"); 2 IMathListener mPlusListener = (x, y) -> x + y;
可以指定參數的類型,這時傳入的參數類型必須匹配,否則編譯錯誤。
1 IMathListener mSubListener = (int x, int y) -> x - y;
Lambda表達式中,修改方法體中引入的外部變量會報錯,即Lambda表達式引用的是值而不是變量。
函數式接口是Java8中提供的一種特殊類型的接口,該接口中只定義了唯一的抽象方法,用作表達式的類型。下面是一個函數式接口的例子。
1 public interface IMathListener { 2 int doMathOperator(int start, int plusValue); 3 }
下面用Lambda表達式聲明了函數式接口IMathListener的實現。
1 IMathListener mSubListener = (x, y) -> x - y; 2 mMaxListener.doMathOperator(10, 5));// 其值:5
對於函數接口而言,接口中唯一方法的命名並不重要了,只要方法簽名和Lambda表達式的類別相匹配即可。但為了增加可讀性,需要參數名稱有意義。
現有的靜態方法也可以支持Lambda表達式。
1 public class Math { 2 public static int doIntPlus(int start, int plusValue) { 3 return start + plusValue; 4 } 5 }
關聯:函數簽名一樣就可以,通過函數調用,直接生成了一個IMathListener對象。
1 IMathListener mPlusListener = Math::doIntPlus;
Lambda表達式都是靜態類型的,在編譯器編譯,所以被引用的方法必須是靜態方法。
每個用作函數接口的接口都應添加 @FunctionalInterface注釋,該注釋會強制 javac 檢查一個接口是否符合函數接口的標准。如果該接口添加給枚舉類型、類或函數不止一個的接口,javac會報錯。
可以人工指定返回值數據類型。
1 overloadedMethod((x)->(String)y);
數據類型推導:Lambda表達式作為參數時,其類型由它的目標類型推導得出,規則如下。
- 如果只有一個可能的目標類型,由相應函數接口里的參數類型推導得出;
- 如果有多個可能的目標類型,由最具體的類型推導得出;
- 如果有多個可能的目標類型且最具體的類型不明確, 則需人為指定類型。
總結:
使用Lambda表達式避免使用大量的匿名內部類,提高代碼可讀性。
Lambda表達式是匿名方法,旨在通過用輕量級機制替換匿名內部類的機制來解決“垂直問題”。
以下是lambda表達式的一些示例:
1 (int x, int y) -> x + y 2 3 () -> 42 4 5 (String s) -> { System.out.println(s); }
第一個表達式采用兩個整數參數,名為x
andy
,並返回它們的和。第二個不帶參數並返回整數42
。第三個接受一個字符串並將其打印到控制台,什么都不返回。
一般語法包括參數列表,箭頭標記->
和正文。正文可以是單個表達式,也可以是語句塊。在表達式中,簡單地評估並返回正文。在塊形式中,body被評估為方法體 - return
語句將控制權返回給匿名方法的調用者; break
並且continue
在頂級是非法的,但當然允許在循環中; 如果正文產生結果,則每個控制路徑必須返回一些內容或拋出異常。
語法針對lambda表達式非常小的常見情況進行了優化,如上所示。例如,表達式 - 體形式消除了對return
關鍵字的需要,否則關鍵字可能代表相對於表達式大小的實質語法開銷。
還期望lambda表達式經常出現在嵌套上下文中,例如方法調用的參數或另一個 lambda表達式的結果。為了在這些情況下最小化噪聲,避免了不必要的分隔符。但是,對於將整個表達式設置為有用的情況,可以用括號括起來,就像任何其他表達式一樣。
以下是語句中出現的lambda表達式的一些示例:
1 FileFilter java = (File f) -> f.getName().endsWith(".java"); 2 3 String user = doPrivileged(() -> System.getProperty("user.name")); 4 5 new Thread(() -> { 6 connectToService(); 7 sendNotification(); 8 }).start();