【Java8新特性】01 函數(shù)式接口和Lambda表達(dá)式你真的會(huì)了嗎

Java8 由Oracle在2014年發(fā)布,是繼Java5之后最具革命性的版本。

Java8吸收其他語言的精髓帶來了函數(shù)式編程,lambda表達(dá)式,Stream流等一系列新特性,學(xué)會(huì)了這些新特性,可以讓你實(shí)現(xiàn)高效編碼優(yōu)雅編碼。

Lambda表達(dá)式小試牛刀 Lambada表達(dá)式可以理解為:可傳遞的匿名函數(shù)的一種簡(jiǎn)潔表達(dá)方式。Lambda表達(dá)式?jīng)]有名稱,同普通方法一樣有參數(shù)列表、函數(shù)主體、返回類型等; 下面簡(jiǎn)單看一個(gè)例子,new一個(gè)線程打印字符串,采用lambda表達(dá)式非常簡(jiǎn)潔:

new Thread(() -> System.out.println("hello java8 lambda")).start()

Thread類接受一個(gè)Runnable類型實(shí)例,查看Jdk源碼發(fā)現(xiàn)Runnable接口是一個(gè)函數(shù)式接口,可以直接用lambda表達(dá)式替代。

@FunctionalInterfacepublic interface Runnable {? ? public abstract void run();}復(fù)制代碼

Lambda表達(dá)式語法非常簡(jiǎn)單:

() -> System.out.println("hello java8 lambda")復(fù)制代碼

()括號(hào)里面是參數(shù)列表,如果只有一個(gè)參數(shù)還可以寫為: a -> System.out.println(a) -> 箭頭為固定寫法; System.out.println("hello java8 lambda") 為函數(shù)主體,如果有多條語句要用花括號(hào)包裹起來, 比如下面這樣:

(a, b) -> {int sum = a + b; return sum;}復(fù)制代碼

綜上,Lambda表達(dá)式模塊可以固化為: (parameter) -> {expression} 或者 (parameter) -> {statements; statements; }

參數(shù)只有一個(gè)可以省略括號(hào)

如果不用Lambda表達(dá)式,使用匿名內(nèi)部類的方式,寫法就不是那么優(yōu)雅了。 // before Java8 new Thread(new Runnable() { @Override public void run() { System.out.println("hello java8 without lambda"); } }).start();

Lambda高階用法 (1)函數(shù)式接口 函數(shù)式接口是只定義了一個(gè)抽象方法的接口。注意Java8中允許存在默認(rèn)方法(default),哪怕有很多默認(rèn)方法,只要有且僅有一個(gè)抽象方法,那么這個(gè)接口仍然是函數(shù)式接口。

函數(shù)式接口通常在類上有一個(gè)注解@FunctionalInterface,如:

@FunctionalInterfacepublic interface Runnable {? ? public abstract void run();}復(fù)制代碼

(2)函數(shù)式接口可以干什么? 通常lambda表達(dá)式與函數(shù)式接口結(jié)合一起用,lambda表達(dá)式以內(nèi)聯(lián)的形式為函數(shù)式接口的抽象方法提供實(shí)現(xiàn),把整個(gè)表達(dá)式作為函數(shù)式接口的實(shí)例。在沒有l(wèi)ambda表達(dá)式之前,我們通常會(huì)使用匿名內(nèi)部類的方式實(shí)現(xiàn),詳細(xì)對(duì)比見第一小節(jié)的實(shí)例代碼。

(3)函數(shù)描述符 函數(shù)式接口抽象方法的簽名基本上就是lambda表達(dá)式的簽名,我們可以將這種對(duì)應(yīng)關(guān)系稱為函數(shù)描述符。由一個(gè)函數(shù)式接口的抽象方法抽象為一個(gè)函數(shù)描述符,這個(gè)過程非常重要,知道了函數(shù)描述符去寫lambda表達(dá)式也就非常容易了。舉個(gè)例子: Runnable接口有一個(gè)抽象方法 void run(), 接受空參數(shù)返回void,那么函數(shù)描述符可以推導(dǎo)為: () -> void lambda表達(dá)式可以寫為 () -> System.out.println("hello java8 lambda")

(4)常用函數(shù)式接口 java8 中常用函數(shù)式接口,針對(duì)基本類型java還定義了IntPredicate, LongPredicate等類型,詳細(xì)可以參考jdk源碼。

函數(shù)式接口

至于 Predicate, Consumer, Function這些函數(shù)式接口具體作用,在后面的文章中筆者會(huì)詳細(xì)介紹,這里只需有個(gè)大體印象即可。

(5)將lambda表達(dá)式重構(gòu)為方法引用 方法引用可以看作是lambda表達(dá)式的一種快捷寫法,它可以調(diào)用特性的方法作為參數(shù)傳遞。你也可以將方法引用看作是lambda表達(dá)式的語法糖,讓lambda表達(dá)式寫起來更加簡(jiǎn)介。舉個(gè)栗子,按學(xué)生年齡排序:

// beforestudents.sort((s1, s2) -> s1.getAge.compareTo(s2.getAge()))));// after 使用方法引用students.sort(Comparator.comparing(Student::getAge()))));復(fù)制代碼

方法引用主要有三類: 靜態(tài)方法的方法引用 valueOf是String類的靜態(tài)方法,方法引用寫為 String::valueOf, 對(duì)應(yīng)lambda表達(dá)式:a -> String.valueOf(a) 任意類型實(shí)例方法的方法引用 length是String類的實(shí)例方法,方法引用寫為 String::length,對(duì)應(yīng)lambda表達(dá)式: (str) -> str.length() 現(xiàn)有對(duì)象的實(shí)例方法的方法引用 第三種容易與第二種混淆,現(xiàn)有對(duì)象指的是在lambda表達(dá)式中調(diào)用外部對(duì)象(不是入?yún)?duì)象)的實(shí)例方法,比如:

String str = "hello java8"; () -> str.length();復(fù)制代碼

對(duì)應(yīng)方法引用寫為 str::length, 注意不是 String::length

最后我們將三類方法引用歸納如下:

三類方法引用歸納
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容