Java8 函數(shù)式編程詳解

Java8 函數(shù)式編程詳解

Author:Dorae
Date:2017年11月1日23:03:26
轉(zhuǎn)載請注明出處

由于切換博客,2018/09/20及之前文章可能會(huì)存在圖片無法查看的問題,請移步這里。


說起Java8,可能很多人都已經(jīng)知道其最大的改進(jìn),就是引入了Lambda表達(dá)式與Stream,畢竟Java9都已近發(fā)布了,Java8發(fā)布了也已經(jīng)近三年。那么,今天我們就先來講一下Java8引入的Lambda表達(dá)式,以及由此引入的函數(shù)式編程,以及函數(shù)式接口。

什么是函數(shù)式編程

函數(shù)式編程并不是Java新提出的概念,其與指令編程相比,強(qiáng)調(diào)函數(shù)的計(jì)算比指令的計(jì)算更重要;與過程化編程相比,其中函數(shù)的計(jì)算可以隨時(shí)調(diào)用。

當(dāng)然,大家應(yīng)該都知道面向?qū)ο蟮奶匦裕ǔ橄蟆⒎庋b、繼承、多態(tài))。其實(shí)在Java8出現(xiàn)之前,我們關(guān)注的往往是某一類對(duì)象應(yīng)該具有什么樣的屬性,當(dāng)然這也是面向?qū)ο蟮暮诵?-對(duì)數(shù)據(jù)進(jìn)行抽象。但是java8出現(xiàn)以后,這一點(diǎn)開始出現(xiàn)變化,似乎在某種場景下,更加關(guān)注某一類共有的行為(這似乎與之前的接口有些類似),這也就是java8提出函數(shù)式編程的目的。如圖1-1所示,展示了面向?qū)ο缶幊痰矫嫦蛐袨榫幊痰淖兓?/p>

圖1-1

為什么需要Lambda表達(dá)式

首先,不得不提增加Lambda的目的,其實(shí)就是為了支持函數(shù)式編程,而為了支持Lambda表達(dá)式,才有了函數(shù)式接口。另外,為了在面對(duì)大型數(shù)據(jù)集合時(shí),為了能夠更加高效的開發(fā),編寫的代碼更加易于維護(hù),更加容易運(yùn)行在多核CPU上,java在語言層面增加了Lambda表達(dá)式。

第一個(gè)Lambda表達(dá)式

前邊廢話了這么多,其實(shí)Lambda就是Java新增的語法而已。當(dāng)然,Lambda(我們認(rèn)為這里包含了方法引用)確實(shí)能夠給我們的開發(fā)帶來許多便利。
首先,在java8之前,如果需要建立一個(gè)線程,很大可能會(huì)寫出下面的代碼:

new Thread(new Runnable()) {
    @Override
    public void run() {
        System.out.println("Hello World!");
    }
}).start();

但是Java8引入Lambda之后,也許這樣寫會(huì)更好:

new Thread(
    () -> System.out.println("Hello world!");
);

很明顯,Lambda可以幫助我們減少模板代碼的書寫,同時(shí)減少了要維護(hù)的匿名內(nèi)部類,當(dāng)然,其作用絕不僅僅這么一點(diǎn)(關(guān)于Lambda的具體使用,讀者可以參考java8函數(shù)式編程這本書,作者解析的很詳細(xì))。接下來我們先來看一下java8關(guān)于接口的的變動(dòng)。

Java8中接口的變化

其實(shí)Java9中關(guān)于接口,又有了進(jìn)一步的變動(dòng),這里我們暫且局限于Java8。在Java8中,接口可以包含靜態(tài)方法,另外還增加了一個(gè)用于修飾方法的關(guān)鍵字--default,稱之為默認(rèn)方法(帶有方法體)。

  • 靜態(tài)方法

其實(shí)Java8中增加靜態(tài)方法,目的完全出于編寫類庫,對(duì)某些行為進(jìn)行抽象(還記得我們之前用類去做嗎?)。但是有一點(diǎn)不同的是:類中的靜態(tài)方法可以繼承,并且可以從實(shí)例獲得引用(并不建議這么做);但是接口中的靜態(tài)方法不能被繼承。

  • 默認(rèn)方法

其實(shí),引入默認(rèn)方法,是不得已而為之,因?yàn)镴ava8引入了函數(shù)式接口,許多像Collection這樣的基礎(chǔ)接口中增加了方法,如果還是一個(gè)傳統(tǒng)的抽象方法的話,那么可能很多第三方類庫就會(huì)變得完全無法使用。為了實(shí)現(xiàn)二進(jìn)制的向后兼容性,引入了帶有方法體、被default修飾的方法--默認(rèn)方法。其主要思想就是如果子類中沒有實(shí)現(xiàn),那么采用父類提供的默認(rèn)實(shí)現(xiàn)。其具體的繼承規(guī)則如圖1-2所示。

image

圖1-2

其中Parent接口中定義了默認(rèn)方法welcome;
Child接口對(duì)默認(rèn)方法進(jìn)行了覆蓋;
ParentImpl繼承了Parent接口的方法;
ChildImpl繼承了Child的方法;
OverridingParent覆蓋了父類的welcome;
OverridingChild最終的welcome來自于OverridingParent。

關(guān)于繼承規(guī)則,可以簡短描述為:類勝于接口;子類勝于父類;如果前兩者都不適用,那么子類要么實(shí)現(xiàn)該方法,要么將該方法聲明為抽象方法。

函數(shù)式接口

關(guān)于接口的變動(dòng),Java8中新定義了一種接口類型,函數(shù)式接口,與其他接口的區(qū)別就是:

  • 函數(shù)式接口中只能有一個(gè)抽象方法(我們在這里不包括與Object的方法重名的方法);
  • 可以有從Object繼承過來的抽象方法,因?yàn)樗蓄惖淖罱K父類都是Object;
  • 接口中唯一抽象方法的命名并不重要,因?yàn)楹瘮?shù)式接口就是對(duì)某一行為進(jìn)行抽象,主要目的就是支持Lambda表達(dá)式。

Java8之前已經(jīng)存在的函數(shù)式接口有:

java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener

另外,Java8還提供了@FunctionalInterface注解來幫助我們標(biāo)識(shí)函數(shù)式接口。另外需要注意的是函數(shù)式接口的目的是對(duì)某一個(gè)行為進(jìn)行封裝,某些接口可能只是巧合符合函數(shù)式接口的定義。

如圖1-3所示,為java8的Function包的結(jié)構(gòu)(即新引入的函數(shù)式接口),圖中綠色表示主要引入的新接口,其他接口基本上都是為了支持基本類型而添加的接口,方法的具體作用圖中有具體說明。

[圖片上傳失敗...(image-7baf51-1537434242538)]

圖1-3

自定義函數(shù)式接口支持Lambda表達(dá)式

看下如下代碼,最終輸出應(yīng)該是兩行"Hello World!",是不是很神奇?

public class Main {
    public static void main(String[] args) {
        Action action = System.out :: println;
        action.execute("Hello World!");
        test(System.out :: println, "Hello World!");
    }

    static void test(Action action, String str) {
        action.execute(str);
    }
}
@FunctionalInterface
interface Action<T> {
    public void execute(T t);
}

小結(jié)

本文對(duì)Lambda以及函數(shù)式接口進(jìn)行了簡要介紹,目的是激發(fā)大家使用Lambda的興趣,步入函數(shù)式編程的大門。

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

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

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