慶哥教你如何使用Java lambda表達(dá)式
在Java8中有一個(gè)很關(guān)鍵的特性叫做lambda表達(dá)式,這個(gè)是在后續(xù)我們經(jīng)常要使用的,所以一定要掌握,對(duì)于lambda表達(dá)式來(lái)說(shuō),必須是函數(shù)式接口(接口中有且僅有一個(gè)方法聲明)才行,接下來(lái)我們一步步來(lái)看!
首先需要清楚lambda表達(dá)式解決的問(wèn)題:
匿名內(nèi)部類的代碼冗余,使其變得簡(jiǎn)潔
接下來(lái)我們看看lambda表達(dá)式如何使用?
lambda表達(dá)式怎么寫
先看一段代碼:
interface OneImpl{
public void hello();
}很簡(jiǎn)單,這里就是定義了一個(gè)簡(jiǎn)單的接口,一個(gè)最普通的接口,接下來(lái)看怎么用:
new OneImpl() {
@Override
public void hello() {
System.out.println("hello");
}
}.hello(); 要注意這里我使用的是匿名內(nèi)部類的形式,當(dāng)然你最熟悉的應(yīng)該是這樣:
OneImpl one = new OneImpl() {
@Override
public void hello() {
System.out.println("hello");
}
};
one.hello();接下來(lái)我們看下使用lambda表達(dá)式是怎樣的:
OneImpl two = () -> {
System.out.println("hello");
};
two.hello();是不是簡(jiǎn)潔很多,不過(guò)看到這里是不是有點(diǎn)懵?這樣的寫法著實(shí)有點(diǎn)不懂啊,沒(méi)關(guān)系,一起來(lái)看:

注意看區(qū)別,這里紅框內(nèi)的都是一樣的,不同的是什么呢?是不是這些:

也就是我們常規(guī)的匿名內(nèi)部類的形式被以下的寫法給代替了:

發(fā)現(xiàn)沒(méi),就是這個(gè):
()->{}然后這個(gè)大括號(hào)里面可以寫一些執(zhí)行邏輯比如:
() -> {System.out.println("hello");}; 所以,簡(jiǎn)單來(lái)說(shuō),一個(gè)小括號(hào),一個(gè)右箭頭,一個(gè)大括號(hào),這就是lambda表達(dá)式啊,不過(guò)這里要注意了,這是lambda最基本的表達(dá)形式,因?yàn)樾±ㄌ?hào)和大括號(hào)里面都可能是有內(nèi)容的,比如上面的例子,大括號(hào)里面有個(gè)輸出語(yǔ)句:
System.out.println("hello lambda");那小括號(hào)里面呢?是啥?可能有人猜到了,就是方法參數(shù),下面來(lái)看個(gè)例子:
interface OneImpl{
public String hello(String s);
}這一次,我們的接口中,聲明的方法是帶有參數(shù)和返回值的,這個(gè)時(shí)候再看lambda的形式:

發(fā)現(xiàn)沒(méi),此時(shí)這里的小括號(hào)里面含有與方法聲明相同的參數(shù)了。而且這里還可以簡(jiǎn)單的寫成這樣:

什么意思呢?就是lambda表達(dá)式這里的小括號(hào)里面的參數(shù),你可以隨便寫一個(gè),而且不用指定類型,其會(huì)自動(dòng)幫你進(jìn)行類型推斷,再看一個(gè)例子:

然后看結(jié)果:

OK,以上就是lambda表達(dá)式的簡(jiǎn)單用法了,我相信你已經(jīng)對(duì)它不再那么陌生了,然后我們接著往下看!
函數(shù)式接口
這是什么?函數(shù)式接口?是不是會(huì)覺(jué)得有一點(diǎn)陌生呢?
首先,我們?cè)倩仡櫹耹ambda表達(dá)式的基本結(jié)構(gòu):
()->{}這里需要注意了:
??要想使用lambda表達(dá)式,必須是函數(shù)式接口才行
什么意思呢?我們看之前定義的這個(gè)接口:
interface OneImpl{
public String hello(String s,int i);
}好像沒(méi)什么特殊的吧,不就是一個(gè)普通的接口嘛?如果非要說(shuō)出來(lái)一點(diǎn)特殊性,是不是就是:
只有一個(gè)方法聲明
好像沒(méi)啥了,不過(guò)這就是重點(diǎn)了,什么是函數(shù)式接口啊,首先,它一定是一個(gè)接口,其次最重要的一點(diǎn):
?函數(shù)式接口有且僅有一個(gè)方法聲明
你要注意了,我這里說(shuō)的是方法聲明,也就是只有聲明沒(méi)有實(shí)現(xiàn),只有方法頭,沒(méi)有方法體!
那么這樣的一個(gè)接口就稱作是函數(shù)式接口,就可以使用lambda表達(dá)式了!也就是說(shuō),要想使用lambda表達(dá)式,必須是函數(shù)式接口才行,那為了滿足這一點(diǎn),確保對(duì)于某些接口來(lái)說(shuō)你可以使用lambda表達(dá)式,那么在Java8中就增加了一個(gè)獨(dú)有的注解:

怎么用呢?簡(jiǎn)單:

這樣一來(lái),你這個(gè)接口就是函數(shù)式接口了,然后我們測(cè)試下:

報(bào)錯(cuò)了,為啥?你這有函數(shù)式接口注解,說(shuō)明這個(gè)接口是一個(gè)函數(shù)式接口,那只能有一個(gè)方法聲明,所以報(bào)錯(cuò)了!
那我們把這個(gè)注解去掉:

但是你就不能用lambda表達(dá)式了!
再舉一個(gè)我們常見(jiàn)的線程的例子:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("開(kāi)啟一個(gè)線程");
}
}).start();我們看下這個(gè)Runnable接口:

發(fā)現(xiàn)沒(méi),是個(gè)函數(shù)式接口,所以我們就可以這樣寫:
new Thread(()->{
System.out.println("開(kāi)啟一個(gè)線程");
}).start();現(xiàn)在你應(yīng)該知道什么是函數(shù)式接口了吧!
注意事項(xiàng)
以上我們大致清楚了lambda表達(dá)式的基本用法,也清楚了函數(shù)式接口的定義,那么其中還有一些需要我們格外注意的事項(xiàng)??
首先讓我們回顧下這句話:
函數(shù)式接口允許有一個(gè)且僅有一個(gè)方法聲明
然后我們看下這段代碼:

看到?jīng)],這里是允許你定義一個(gè)默認(rèn)的方法的,這個(gè)是從Java8開(kāi)始增加的特性,再看一個(gè):

明白唄,就是允許你定義多個(gè)默認(rèn)方法,然后還有如下的一個(gè)例子:

這說(shuō)明在函數(shù)式接口中除了可以定義多個(gè)默認(rèn)方法之外還可以定義多個(gè)static靜態(tài)方法,那如何使用:

ok,上圖描述還是很直觀的!
那么,你學(xué)會(huì)了嗎?記得點(diǎn)贊哦!
