1.21 Lambda表达式
Lambda 表達(dá)式(Lambda expression)是一個(gè)匿名函數(shù),基于數(shù)學(xué)中的λ演算得名,也可稱為閉包(Closure)。
Lambda 表達(dá)式是推動(dòng) Java 8 發(fā)布的重要新特性,它允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中),下面通過例 1 來理解 Lambda 表達(dá)式的概念。
例 1
先定義一個(gè)計(jì)算數(shù)值的接口,代碼如下。
Calculable 接口只有一個(gè)方法 calculateInt,參數(shù)是兩個(gè) int 類型,返回值也是 int 類型。實(shí)現(xiàn)方法代碼如下:
public class Test{/*** 通過操作符,進(jìn)行計(jì)算** @param opr 操作符* @return 實(shí)現(xiàn)Calculable接口對象*/public static Calculable calculate(char opr) {Calculable result;if (opr == '+') {// 匿名內(nèi)部類實(shí)現(xiàn)Calculable接口13 result = new Calculable() {// 實(shí)現(xiàn)加法運(yùn)算@Override16 public int calculateInt(int a, int b) {return a + b;}};} else {// 匿名內(nèi)部類實(shí)現(xiàn)Calculable接口23 result = new Calculable() {// 實(shí)現(xiàn)減法運(yùn)算@Override26 public int calculateInt(int a, int b) {return a - b;}};}return result;} }方法 calculate 中 opr 參數(shù)是運(yùn)算符,返回值是實(shí)現(xiàn) Calculable 接口對象。代碼第 13 行和第 23 行都采用匿名內(nèi)部類實(shí)現(xiàn) Calculable 接口。代碼第 16 行實(shí)現(xiàn)加法運(yùn)算。代碼第 26 行實(shí)現(xiàn)減法運(yùn)算。
public static void main(String[] args) {int n1 = 10;int n2 = 5;// 實(shí)現(xiàn)加法計(jì)算Calculable對象 5 Calculable f1 = calculate('+');// 實(shí)現(xiàn)減法計(jì)算Calculable對象 7 Calculable f2 = calculate('-');// 調(diào)用calculateInt方法進(jìn)行加法計(jì)算 9 System.out.println(n1 + "+" + n2 + "=" + f1.calculateInt(n1, n2));// System.out.printf("%d + %d = %d \n", n1, n2, f1.calculateInt(n1, n2));// 調(diào)用calculateInt方法進(jìn)行減法計(jì)算 12 System.out.println(n1 + "-" + n2 + "=" + f1.calculateInt(n1, n2));// System.out.printf("%d - %d = %d \n", n1, n2, f2.calculateInt(n1, n2)); }代碼第 5 行中 f1 是實(shí)現(xiàn)加法計(jì)算 Calculable 對象,代碼第 7 行中 f2 是實(shí)現(xiàn)減法計(jì)算 Calculable 對象。代碼第 9 行和第 12 行才進(jìn)行方法調(diào)用。
上述代碼中列出了兩種輸出方式,下面簡單介紹一下 Java 中常見的輸出函數(shù):
輸出結(jié)果如下:
10+5=15 10-5=15例 1 使用匿名內(nèi)部類的方法 calculate 代碼很臃腫,Java 8 采用 Lambda 表達(dá)式可以替代匿名內(nèi)部類。修改之后的通用方法 calculate 代碼如下:
/** * 通過操作符,進(jìn)行計(jì)算 * @param opr 操作符 * @return 實(shí)現(xiàn)Calculable接口對象 */ public static Calculable calculate(char opr) {Calculable result;if (opr == '+') {// Lambda表達(dá)式實(shí)現(xiàn)Calculable接口 10 result = (int a, int b) -> {return a + b;};} else {// Lambda表達(dá)式實(shí)現(xiàn)Calculable接口 15 result = (int a, int b) -> {return a - b;};}return result; }代碼第 10 行和第 15 行用 Lambda 表達(dá)式替代匿名內(nèi)部類,可見代碼變得簡潔。通過以上示例我們發(fā)現(xiàn),Lambda 表達(dá)式是一個(gè)匿名函數(shù)(方法)代碼塊,可以作為表達(dá)式、方法參數(shù)和方法返回值。
Lambda 表達(dá)式標(biāo)準(zhǔn)語法形式如下:
(參數(shù)列表) -> {// Lambda表達(dá)式體 }->被稱為箭頭操作符或 Lambda 操作符,箭頭操作符將 Lambda 表達(dá)式拆分成兩部分:
- 左側(cè):Lambda 表達(dá)式的參數(shù)列表。
- 右側(cè):Lambda 表達(dá)式中所需執(zhí)行的功能,用{ }包起來,即 Lambda 體。
Java Lambda 表達(dá)式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
代碼簡潔,開發(fā)迅速
方便函數(shù)式編程
非常容易進(jìn)行并行計(jì)算
Java 引入 Lambda,改善了集合操作(引入 Stream API)
缺點(diǎn):
代碼可讀性變差
在非并行計(jì)算中,很多計(jì)算未必有傳統(tǒng)的 for 性能要高
不容易進(jìn)行調(diào)試
函數(shù)式接口
Lambda 表達(dá)式實(shí)現(xiàn)的接口不是普通的接口,而是函數(shù)式接口。如果一個(gè)接口中,有且只有一個(gè)抽象的方法(Object 類中的方法不包括在內(nèi)),那這個(gè)接口就可以被看做是函數(shù)式接口。這種接口只能有一個(gè)方法。如果接口中聲明多個(gè)抽象方法,那么 Lambda 表達(dá)式會(huì)發(fā)生編譯錯(cuò)誤:
The target type of this expression must be a functional interface這說明該接口不是函數(shù)式接口,為了防止在函數(shù)式接口中聲明多個(gè)抽象方法,Java 8 提供了一個(gè)聲明函數(shù)式接口注解 @FunctionalInterface,示例代碼如下。
// 可計(jì)算接口 @FunctionalInterface public interface Calculable {// 計(jì)算兩個(gè)int數(shù)值int calculateInt(int a, int b); }在接口之前使用 @FunctionalInterface 注解修飾,那么試圖增加一個(gè)抽象方法時(shí)會(huì)發(fā)生編譯錯(cuò)誤。但可以添加默認(rèn)方法和靜態(tài)方法。
@FunctionalInterface 注解與 @Override 注解的作用類似。Java 8 中專門為函數(shù)式接口引入了一個(gè)新的注解 @FunctionalInterface。該注解可用于一個(gè)接口的定義上,一旦使用該注解來定義接口,編譯器將會(huì)強(qiáng)制檢查該接口是否確實(shí)有且僅有一個(gè)抽象方法,否則將會(huì)報(bào)錯(cuò)。需要注意的是,即使不使用該注解,只要滿足函數(shù)式接口的定義,這仍然是一個(gè)函數(shù)式接口,使用起來都一樣。
提示:Lambda 表達(dá)式是一個(gè)匿名方法代碼,Java 中的方法必須聲明在類或接口中,那么 Lambda 表達(dá)式所實(shí)現(xiàn)的匿名方法是在函數(shù)式接口中聲明的。
總結(jié)
以上是生活随笔為你收集整理的1.21 Lambda表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1.20 Java8新特性:Effect
- 下一篇: 1.22 Lambda表达式的3种简写方