Java8 Lambda表達(dá)式入門
可能很多人都聽說過java8的新特性----Lambada表達(dá)式,但可能很多人都不知道Lambda表達(dá)式到底有什么用,下面我?guī)Т蠹依斫庖幌翷ambada表達(dá)式。
在平時的編程中,我們常常會用到匿名內(nèi)部類,見下面代碼:
package 示例;
import static org.junit.Assert.*;//
import org.junit.Test;
public class LambdaTest {
@Test
public void testOld1() {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("原始方法使用匿名內(nèi)部類");
}
}).start();
}
}
上述代碼運(yùn)用到了匿名內(nèi)部類,但你們有沒有發(fā)現(xiàn),接口名和方法名在這段代碼邏輯中是固定的,也就是說我們通過實(shí)現(xiàn)Runnable接口就必定實(shí)現(xiàn)父類接口中的run方法。寫一萬次上述代碼,只有run方法內(nèi)部的算法邏輯是改變的。
java8也就引入了一個新特性-----Lambda表達(dá)式
package 示例;
import static org.junit.Assert.*;
import org.junit.Test;
public class LambdaTest {
@Test
public void testNew1(){
/*此處用Lambda表達(dá)式,省略了接口名“new Runnable(){}”,以及接口中需要實(shí)現(xiàn)的方法名,以及修飾方法關(guān)鍵字(public void),只留下run方法用來傳參數(shù)的“()”。因?yàn)閞un方法沒有參數(shù),所以括號中什么也沒有 (這里的圓括號就是run方法的括號,只是省略了方法名)*/
new Thread(()->System.out.println("Lambda表達(dá)式")).start();
}
}
在上面的代碼中,我們用Lambda表達(dá)式代替了傳統(tǒng)的匿名內(nèi)部類形式的Java代碼,Lambda表達(dá)式如下:
()->System.out.println("Lambda表達(dá)式")
被替換的傳統(tǒng)代碼如下:
new Runnable(
public void run(){
System.out.println("匿名內(nèi)部類");
}
)
(一)我們現(xiàn)在來看看為什么可以省略這些東西呢
(1)為什么可以省略接口名:
因?yàn)樵贚ambda表達(dá)式外面有new Thread()。而我們根據(jù)多線程的學(xué)習(xí)知道,Thread類的構(gòu)造器如果只傳入一個參數(shù),那必定是Runnable接口實(shí)現(xiàn)類的實(shí)例。
public Thread(Runnable target)
所以編譯器在編譯的時候,是可以推斷出來我們后面匿名內(nèi)部類實(shí)現(xiàn)的接口是什么(Lambada表達(dá)式就是匿名內(nèi)部類的精簡寫法),因此Lambda表達(dá)式將接口名省略。
(2)為什么可以省略接口中的方法名
通過上面我們知道了,編譯器可以推導(dǎo)匿名內(nèi)部類實(shí)現(xiàn)的接口名。那Runnable接口中只有一個抽象方法,因此編譯器同樣可以推導(dǎo)出實(shí)現(xiàn)類中的方法名。
(二)Lambda表達(dá)式的具體語法
語法:(參數(shù)列表)->{函數(shù)體};
注:Lambda表達(dá)式省略了匿名內(nèi)部類的接口名、和方法名,目的就是讓我們專注于接口方法的實(shí)現(xiàn)部分。
(1)參數(shù)列表規(guī)則
-
如果沒有參數(shù),直接用“()”表示。()不能省略。
-
如果只有一個參數(shù),并且參數(shù)寫了類型,則一定要加()
-
如果只寫了一個參數(shù),并且參數(shù)不寫類型,那么這個參數(shù)外面不用加“()”。
- 如果有兩個或多個參數(shù),則“()”必須寫。
(2)函數(shù)體規(guī)則
- 如果函數(shù)體只有一行,那么可以省略“{}”。
- 如果函數(shù)體有多行,則“{}”不能省略。
- 如果函數(shù)體有多行,并且該函數(shù)有返回值,則不能省略“return”關(guān)鍵字。
- 如果函數(shù)體是一行,并且函數(shù)有返回值,則必須省略“return”關(guān)鍵字(由編譯器自己推導(dǎo)返回類型)
java8引入Lambda表達(dá)式的唯一目的就是簡化函數(shù)式接口的使用。(暫時可以理解為簡化匿名內(nèi)部類的使用)
(三)Lambda表達(dá)式異常處理
- Lambda表達(dá)式產(chǎn)生的異常在函數(shù)體中try-catch。
- 在接口的抽象方法定義時,聲明拋出異常。
(四)Lambda表達(dá)式使用場景(局限性)
由上面的的學(xué)習(xí)可知,Lambda表達(dá)式實(shí)際上就是匿名內(nèi)部類的一種精簡寫法。在編譯時還是會被推導(dǎo)為匿名內(nèi)部類,說白了Lambda表達(dá)式就是一種“語法糖”。根據(jù)Lambda表達(dá)式省略接口名與方法名的原理可知,只有在編譯器自身能夠推導(dǎo)出匿名內(nèi)部類實(shí)現(xiàn)的接口時,才能使用Lambda表達(dá)式。在能夠推導(dǎo)出接口后,必須滿足接口中只有一個抽象方法才能運(yùn)用Lambda表達(dá)式。
補(bǔ)充說明:在Java中,通常將只有一個抽象方法的接口稱為函數(shù)式接口,我們可以在接口上添加“@FunctionalInterface”標(biāo)簽,表明這是一個函數(shù)式接口。
總結(jié)
Java8新增的這一特性唯一的目的就是簡化函數(shù)式接口的使用,它本身不是一個新的語法知識,底層實(shí)際上還是匿名內(nèi)部類,所以學(xué)會靈活使用Lambda表達(dá)式,可以提高代碼的開發(fā)效率,但在后期維護(hù)中降低了代碼的可讀性,博友們可以嘗試一下這種“語法糖”。
下面是博主的其他文章,喜歡的博友點(diǎn)個關(guān)注,感謝您的支持。
JDK8以前匿名內(nèi)部類訪問局部變量為什么必須用final修飾
Validate插件的自定義表單校驗(yàn)入門(結(jié)合Ajax實(shí)現(xiàn)用戶名的數(shù)據(jù)庫查重)

浙公網(wǎng)安備 33010602011771號