函數(shù)式接口和Lambda表達(dá)式深入理解


我上一篇文章介紹了函數(shù)式接口和Lambda表達(dá)式压储,以及Java解決所謂的閉包逝她。
這次深入一下技竟。

0x00 函數(shù)式接口

前面講了一下函數(shù)式接口,不過(guò)可能只是講了個(gè)大概勺拣,大致講了一下什么是函數(shù)式接口

  • 函數(shù)式接口就是:一個(gè)interface奶赠,里面只有一個(gè)抽象方法,其他什么都沒(méi)有药有。
  • FunctionalInterface注解標(biāo)注一個(gè)函數(shù)式接口毅戈,不能標(biāo)注方法愤惰,枚舉苇经,屬性這些。
  • 如果接口被標(biāo)注了@FunctionalInterface宦言,這個(gè)類就必須符合函數(shù)式接口的規(guī)范
  • 即使一個(gè)接口沒(méi)有標(biāo)注@FunctionalInterface扇单,如果這個(gè)接口滿足函數(shù)式接口規(guī)則,依舊被當(dāng)作函數(shù)式接口奠旺。

這次我們來(lái)用代碼來(lái)深入了解函數(shù)式接口

Demo01

如上圖蜘澜,只包含一個(gè)抽象方法是最普通的函數(shù)式接口

兩個(gè)抽象方法,報(bào)錯(cuò)

再看响疚,當(dāng)接口有兩個(gè)抽象方法的時(shí)候鄙信,就不在是函數(shù)式接口了,使用@FunctionalInterface標(biāo)注編譯時(shí)會(huì)報(bào)錯(cuò)

特例-01

奇怪的是這里有3個(gè)抽象方法忿晕,為什么不報(bào)錯(cuò)装诡?
我們知道toStringequals方法是Object的方法,Java基礎(chǔ)告訴我們践盼,Object是所有類的默認(rèn)父類鸦采,也就是說(shuō)任何對(duì)象都會(huì)包含Object里面的方法,即使是函數(shù)式接口的實(shí)現(xiàn)宏侍,也會(huì)有Object的默認(rèn)方法赖淤,所以:重寫(xiě)Object中的方法蜀漆,不會(huì)計(jì)入接口方法中,除了final不能重寫(xiě)的,Object中所能重寫(xiě)的方法搬素,寫(xiě)到接口中祈匙,不會(huì)影響函數(shù)式接口的特性

特例-02

Java8 允許接口中含有非抽象方法,這種在接口中使用default修飾的非抽象方法稱為默認(rèn)方法鲜侥,默認(rèn)方法也不會(huì)影響函數(shù)式接口的特性褂始。我們依然可以認(rèn)為DemoConsumer是一個(gè)函數(shù)式接口。

0x01 Lambda表達(dá)式深入

Lambda表達(dá)式的形式如下

(param1, param2, param3, param4…)->{ doing……}描函;

由此引申出多種寫(xiě)法:

//1.
() -> System.out.println("Hello Lambda");
//2.
number1 -> int a = number1 * 2;
//3.
(number1, number2) -> int a = number1 + number2;
//4.
(number1, number2) -> {
 int a = number1 + number2;
 System.out.println(a);
}

下面通過(guò)重構(gòu)一段代碼崎苗,來(lái)深入了解一下Lambda表達(dá)式

public class FunctionalInterfaceTest {
    public static void main(String[] args) {
        List<String> demoList = Arrays.asList( "Zing", "阿三", "小明", "小紅", "趙日天");
       rollCall(demoList);
    }
    public static void rollCall(List<? extends String> list){
        for(String name : list){
            if(name.startsWith("小")){
                System.out.println(name);
            }
        }
    }
}

如果希望篩選的條件能自由定義狐粱,而不是name.startsWith("小")寫(xiě)死,并且希望找到人名后胆数,不是簡(jiǎn)單的System.out.println(name);肌蜻,而是能做一些其他的事情。
繼續(xù)重構(gòu):

/**
 * 函數(shù)式接口
 * @param <T>
 */
@FunctionalInterface
interface Checker<T extends String>{
    boolean check(T t);
}

@FunctionalInterface
interface Out<T>{
    void achievement(T t);
}

public class FunctionalInterfaceTest {
    /**
     * 點(diǎn)名
     */
    @Test
    public void testLambda() {
        List<String> demoList = Arrays.asList("小明", "Zing", "阿三", "小紅", "趙日天");
        rollCall(demoList,
                name-> name.startsWith("Z"),
                name->{
                    String rate = name + "是單身狗!";
                    System.out.println(rate);
                });
    }

    /**
     * 點(diǎn)名邏輯
     * @param list
     * @param checker
     */
    public void rollCall(List<? extends String> list, Checker checker,Out out){
        for(String name : list){
            if(checker.check(name)){
                out.achievement(name);
            }
        }
    }
}

運(yùn)行結(jié)果

一不小心暴露了什么必尼。哈哈哈

通過(guò)上面的重構(gòu)蒋搜,很明顯,這么寫(xiě)也是合法的

        Checker checker =  name-> name.startsWith("Z"),
        Out estimator = name->{
            String rate = name + "是單身狗!";
            System.out.println(rate);
        };

由此可以知道判莉,Lambda和函數(shù)式接口是等價(jià)的豆挽。

0x02 補(bǔ)充

  • 類型
    有人會(huì)很奇怪,為什么Checker checker = name-> name.startsWith("Z")這樣寫(xiě)的時(shí)候券盅,name會(huì)被當(dāng)成String 類型帮哈?

這是Java的類型推斷,大致邏輯是編譯器知道函數(shù)式接口方法的輸入?yún)?shù)類型锰镀,所以無(wú)論前面的參數(shù)是什么名字但汞,都會(huì)被當(dāng)成方法所需要的參數(shù)類型。

  • 簡(jiǎn)單縮寫(xiě)
    還有一個(gè)奇怪的地方name->name.startsWith("Z")為什么這樣寫(xiě)也可以互站?
    為什么不是寫(xiě)成``name->{ return name.startsWith("Z");}` 私蕾。
    很明顯,后面的寫(xiě)法是沒(méi)有錯(cuò)的胡桃,

但是Idea會(huì)有一個(gè)虛線踩叭,說(shuō)明不需要寫(xiě)return


展開(kāi)看說(shuō)明

當(dāng)只需要執(zhí)行一條語(yǔ)句的時(shí)候,lambda支持這種簡(jiǎn)潔返回翠胰。所以為什么拒絕呢容贝?

  • 外部參數(shù)
    Lambda表達(dá)式是不能操作外部對(duì)象的,因?yàn)長(zhǎng)ambda 實(shí)質(zhì)上是接口的子對(duì)象之景,只能訪問(wèn)靜態(tài)資源和本身的內(nèi)部變量斤富。

報(bào)錯(cuò)!

編譯器會(huì)要求將外部變量使用final修飾锻狗。

  • 和方法引用結(jié)合
    方法引用Method References是Java8配合Lambda一起做出的新特性满力,當(dāng)Lambda表達(dá)式里面只執(zhí)行已知的方法的時(shí)候,可以使用方法引用來(lái)寫(xiě)出跟簡(jiǎn)潔易讀的代碼
List<String> demoList = Arrays.asList("小明", "Zing", "阿三", "小紅", "趙日天");
demoList.forEach(System.out::println);

看到這里想必心里不禁想說(shuō)轻纪,我擦油额,好簡(jiǎn)潔!
官方給出了4種方法引用

Kinds of Method References

| Kind | Example|
| ---- |----|
|Reference to a static method|ContainingClass::staticMethodName|
|Reference to an instance method of a particular object|containingObject::instanceMethodName|
|Reference to an instance method of an arbitrary object of a particular type|ContainingType::methodName|
|Reference to a constructor| ClassName::new|
來(lái)源:
http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

我想我就不用翻譯了吧刻帚,出門(mén)百度翻譯??


love&peace
FS全棧計(jì)劃目錄:https://micorochio.github.io/fs-plan/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末潦嘶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子崇众,更是在濱河造成了極大的恐慌掂僵,老刑警劉巖航厚,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異锰蓬,居然都是意外死亡阶淘,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)互妓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)溪窒,“玉大人,你說(shuō)我怎么就攤上這事冯勉〕喊觯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵灼狰,是天一觀的道長(zhǎng)宛瞄。 經(jīng)常有香客問(wèn)我,道長(zhǎng)交胚,這世上最難降的妖魔是什么份汗? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮蝴簇,結(jié)果婚禮上杯活,老公的妹妹穿的比我還像新娘。我一直安慰自己熬词,他們只是感情好旁钧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著互拾,像睡著了一般歪今。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上颜矿,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天寄猩,我揣著相機(jī)與錄音,去河邊找鬼骑疆。 笑死田篇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的封断。 我是一名探鬼主播斯辰,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坡疼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起衣陶,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤柄瑰,失蹤者是張志新(化名)和其女友劉穎闸氮,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體教沾,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒲跨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了授翻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片或悲。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖堪唐,靈堂內(nèi)的尸體忽然破棺而出巡语,到底是詐尸還是另有隱情,我是刑警寧澤淮菠,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布男公,位于F島的核電站,受9級(jí)特大地震影響合陵,放射性物質(zhì)發(fā)生泄漏枢赔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一拥知、第九天 我趴在偏房一處隱蔽的房頂上張望踏拜。 院中可真熱鬧,春花似錦低剔、人聲如沸执隧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)镀琉。三九已至,卻和暖如春蕊唐,著一層夾襖步出監(jiān)牢的瞬間屋摔,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工替梨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钓试,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓副瀑,卻偏偏與公主長(zhǎng)得像弓熏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子糠睡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容