日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

淺談Java 8的函數式編程

瀏覽:188日期:2022-09-06 10:11:15

關于“Java 8為Java帶來了函數式編程”已經有了很多討論,但這句話的真正意義是什么?

本文將討論函數式,它對一種語言或編程方式意味著什么。在回答“Java 8的函數式編程怎么樣”之前,我們先看看Java的演變,特別是它的類型系統,我們將看到Java 8的新特性,特別是Lambda表達式如何改變Java的風景,并提供函數式編程風格的主要優勢。

函數式編程語言是什么?

函數式編程語言的核心是它以處理數據的方式處理代碼。這意味著函數應該是第一等級(First-class)的值,并且能夠被賦值給變量,傳遞給函數等等。

事實上,很多函數式語言比這走得更遠,將計算和算法看得比它們操作的數據更重要。其中有些語言想分離程序狀態和函數(以一種看起來有點對立的方式,使用面向對象的語言,這通常會將它們聯系得更緊密)。

Clojure編程語言就是一個這樣的例子,盡管它運行于基于類的Java虛擬機,Clojure的本質是函數式語言,并且在高級語言源程序中不直接公布類和對象(盡管提供了與Java良好的互操作性)。

下面顯示的是一個Clojure函數,用于處理日志,是一等公民(First-class citizen),并且不需要綁定一個類而存在。

(defn build-map-http-entries [log-file] (group-by :uri (scan-log-for-http-entries log-file)))

當寫在函數中的程序,對給定的輸入(不論程序中的其它狀態如何)總是返回相同的輸出,并且不會產生其它影響,或者改變任何程序狀態,這時候函數式編程是最有用的。它們的行為與數學函數相同,有時候把遵循這個標準的函數稱為“純”函數。

純函數的巨大好處是它們更容易推論,因為它們的操作不依賴于外部狀態。函數能夠很容易地結合在一起,這在開發者工作流風格中很常見,例如Lisp方言和其它具有強函數傳統的語言中很普遍的REPL(Read, Execute, Print, Loop)風格。

非函數式編程語言中的函數式編程

一種語言是不是函數式并不是非此即彼的狀態,實際上,語言存在于圖譜上。在最末端,基本上是強制函數式編程,通常禁止可變的數據結構。Clojure就是一種不接受可變數據的語言。

不過,也有一些其它語言,通常以函數方式編程,但語言并不強制這一點。Scala就是一個例子,它混和了面向對象和函數式語言。允許函數作為值,例如:

val sqFn = (x: Int) => x * x

同時保留與Java非常接近的類和對象語法。

另一個極端,當然,使用完全非函數式語言進行函數式編程是可能的,例如C語言,只要維持好合適的程序員準則和慣例。

考慮到這一點,函數式編程應該被看作是有兩個因素的函數,其中一個與編程語言相關,另一個是用該語言編寫的程序:

1)底層編程語言在多大程度上支持,或者強制函數式編程?

2)這個特定的程序如何使用語言提供的函數式特性?它是否避免了非函數式特性,例如可變狀態?

Java的一些歷史

Java是一種固執己見的語言,它具有很好的可讀性,初級程序員很容易上手,具有長期穩定性和可支持性。但這些設計決定也付出了一定的代價:冗長的代碼,類型系統與其它語言相比顯得缺乏彈性。

然而,Java的類型系統已經在演化,雖然在語言的歷史當中相對比較慢。我們來看看這些年來它的一些形式。

Java最初的類型系統

Java最初的類型系統至今已經超過15年了。它簡單而清晰,類型包括引用類型和基本類型。類、接口或者數組屬于引用類型。

類是Java平臺的核心,類是Java平臺將會加載、或鏈接的功能的基本單位,所有要執行的代碼都必須駐留于一個類中。接口不能直接實例化,而是要通過一個實現了接口API的類。數組可以包含基本類型、類的實例或者其它數組。基本類型全部由平臺定義,程序員不能定義新的基本類型。

從最早開始,Java的類型系統一直堅持很重要的一點,每一種類型都必須有一個可以被引用的名字。這被稱為“標明類型(Nominative typing)”,Java是一種強標明類型語言。

即使是所謂的“匿名內部類”也仍然有類型,程序員必須能引用它們,才能實現那些接口類型:

Runnable r = new Runnable() { public void run() { System.out.println('Hello World!'); } };

換種說法,Java中的每個值要么是基本類型,要么是某個類的實例。

命名類型(Named Type)的其它選擇

其它語言沒有這么迷戀命名類型。例如,Java沒有這樣的Scala概念,一個實現(特定簽名的)特定方法的類型。在Scala中,可以這樣寫:

x : {def bar : String}

記住,Scala在右側標示變量類型(冒號后面),所以這讀起來像是“x是一種類型,它有一個方法bar返回String”。我們能用它來定義類似這樣的Scala方法:

def showRefine(x : {def bar : String}) = { print(x.bar) }

然后,如果我們定義一個合適的Scala對象:

object barBell { def bar = 'Bell' }

然后調用showRefine(barBell),這就是我們期待的事:

showRefine(barBell) Bell

這是一個精化類型(Refinement typing)的例子。從動態語言轉過來的程序員可能熟悉“鴨子類型(Duck typing)”。結構精化類型(Structural refinement typing)是類似的,除了鴨子類型(如果它走起來像鴨子,叫起來像鴨子,就可以把它當作鴨子)是運行時類型,而這些結構精化類型作用于編譯時。

在完全支持結構精化類型的語言中,這些精化類型可以用在程序員可能期望的任何地方,例如方法參數的類型。而Java,相反地,不支持這樣的類型(除了幾個稍微怪異的邊緣例子)。

Java 5類型系統

Java 5的發布為類型系統帶來了三個主要新特性,枚舉、注解和泛型。

枚舉類型(Enum)在某些方面與類相似,但是它的屬性只能是指定數量的實例,每個實例都不同并且在類描述中指定。主要用于“類型安全的常量”,而不是當時普遍使用的小整數常量,枚舉構造同時還允許附加的模式,有時候這非常有用。注解(Annotation)與接口相關,聲明注解的關鍵字是@interface,以@開始表示這是個注解類型。正如名字所建議的,它們用于給Java代碼元素做注釋,提供附加信息,但不影響其行為。此前,Java曾使用“標記接口(Marker interface)”來提供這種元數據的有限形式,但注解被認為更有靈活性。Java泛型提供了參數化類型,其想法是一種類型能扮演其它類型對象的“容器”,無需關心被包含類型的具體細節。裝配到容器中的類型通常稱為類型參數。

Java 5引入的特性中,枚舉和注解為引用類型提供了新的形式,這需要編譯器特殊處理,并且有效地從現有類型層級結構分離。

泛型為Java的類型系統增加了顯著額外的復雜性,不僅僅因為它們是純粹的編譯時特性,還要求Java開發人員應注意,編譯時和運行時的類型系統彼此略有不同。

盡管有這些變化,Java仍然保持標明類型。類型名稱現在包括List(讀作:“List-of-String”)和Map, CachedObject>(“Map-of-Class-of-Unknown-Type-to-CachedObject”),但這些仍然是命名的類型,并且每個非基本類型的值仍是某個類的實例。

Java 6和7引入的特性

Java 6基本上是一個性能優化和類庫增強的版本。類型系統的唯一變化是擴大注解角色,發布可插拔注解處理功能。這對大多數開發者沒有任何影響,Java 6中也沒有真正提供可插拔類型系統。

Java 7的類型系統沒有重大改變。僅有的一些新特性,看起來都很相似:

javac編譯器中類型推斷的小改進。簽名多態性分派(Signature polymorphic dispatch),用于方法句柄(Method handle)的實現細節,而這在Java 8中又反過來用于實現Lambda表達式。Multi-catch提供了一些“代數數據類型”的小跟蹤信息,但這些完全是javac內部的,對最終用戶程序員沒有任何影響。Java 8的類型系統

縱觀其歷史,Java基本上已經由其類型系統所定義。它是語言的核心,并且嚴格遵守著標明類型。從實際情況來看,Java類型系統在Java 5和7之間沒有太大變化。

乍一看,我們可能期望Java 8改變這種狀況。畢竟,一個簡單的Lambda表達式似乎讓我們移除了標明類型:

() -> { System.out.println('Hello World!'); }

這是個沒有名字、沒有參數的方法,返回void。它仍然是完全靜態類型的,但現在是匿名的。

我們逃脫了名詞的王國?這真的是Java的一種新的類型形式?

也許不幸的是,答案是否定的。JVM上運行的Java和其它語言,非常嚴格地限制在類的概念中。類加載是Java平臺的安全和驗證模式的中心。簡單地說,不通過類來表示一種類型,這是非常非常難的。

Java 8沒有創建新的類型,而是通過編譯器將Lambda表達式自動轉換成一個類的實例。這個類由類型推斷來決定。例如:

Runnable r = () -> { System.out.println('Hello World!'); };

右側的Lambda表達式是個有效的Java 8的值,但其類型是根據左側值推斷的,因此它實際上是Runnable類型的值。需要注意的是,如果沒有正確地使用Lambda表達式,可能會導致編譯器錯誤。即使是引入了Lambda,Java也沒有改變這一點,仍然遵守著標明類型。

Java 8的函數式編程怎么樣?

最后,讓我們回到本文開頭提出的問題,“Java 8的函數式編程怎么樣?”

Java 8之前,如果開發者想以函數式風格編程,他或她只能使用嵌套類型(通常是匿名內部類)作為函數代碼的替代。默認的Collection類庫不會為這些代碼提供任何方便,可變性的魔咒也始終存在。

Java 8的Lambda表達式沒有神奇地轉變成函數式語言。相反,它的作用仍是創建強制的強命名類型語言,但有更好的語法支持Lambda表達式函數文本。與此同時,Collection類庫也得到了增強,允許Java開發人員開始采用簡單的函數式風格(例如filter和map)簡化笨重的代碼。

Java 8需要引入一些新的類型來表示函數管道的基本構造塊,如java.util.function中的Predicate、Function和Consumer接口。這些新增的功能使Java 8能夠“稍微函數式編程”,但Java需要用類型來表示它們(并且它們位于工具類包,而不是語言核心),這說明標明類型仍然束縛著Java語言,它離純粹的Lisp方言或者其它函數式語言是多么的遙遠。

除了以上這些,這個函數式語言能量的小集合很可能是所有大多數開發者日常開發所真正需要的。對于高級用戶,還有(JVM或其它平臺)其它語言,并且毫無疑問,將繼續蓬勃發展。

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品一区二区男人吃奶| 国产精品黄色| 正在播放日韩精品| 国产精品一站二站| 欧美一区精品| 国产精品v日韩精品v欧美精品网站 | 久久久影院免费| 久久人人精品| 精品一区亚洲| 西西人体一区二区| 97精品国产一区二区三区 | 日韩一区欧美| 久久久久国产| 欧美午夜不卡影院在线观看完整版免费| 蜜桃国内精品久久久久软件9| 亚洲精品电影| 亚洲一级大片| 国产精品欧美三级在线观看 | 欧美日韩少妇| 亚洲欧洲美洲国产香蕉| 久久国产麻豆精品| 麻豆精品少妇| www成人在线视频| 亚洲一区二区网站| 亚洲精品国产精品粉嫩| 国产精品欧美三级在线观看| 裤袜国产欧美精品一区| 欧美日韩免费看片| 日韩亚洲精品在线| 日韩不卡一区二区三区| 精品一二三区| 好看的av在线不卡观看| 亚洲色图国产| 精品高清久久| 欧美日韩四区| 国产精品天堂蜜av在线播放| 日韩在线中文| 在线一区二区三区视频| 国产精品久久777777毛茸茸| 91欧美国产| 一区福利视频| 热久久久久久| 国产麻豆久久| 亚洲精品日本| 国产一区二区三区四区五区| 欧美在线影院| 日本vs亚洲vs韩国一区三区二区| 精品久久视频| 日韩午夜免费| 麻豆精品少妇| 黄色亚洲精品| 国产精品久久久免费| 亚洲性视频h| 欧美日本三区| 久久国产亚洲| 久久国产乱子精品免费女| 日韩精品久久久久久久电影99爱| 亚洲毛片在线| 91精品精品| 国产精品资源| 黄色在线一区| 国产69精品久久| 亚洲综合激情在线| 免费在线小视频| 国产精品欧美日韩一区| 国产模特精品视频久久久久| 日韩av专区| 日韩va亚洲va欧美va久久| 国产一区2区| 综合激情五月婷婷| 日韩不卡在线| 国产精品久久国产愉拍| 久久xxxx精品视频| 久久影院午夜精品| 91亚洲精品在看在线观看高清| www成人在线视频| 久久av日韩| 免费美女久久99| 久久久久国产精品一区二区| 国产欧美一区二区三区国产幕精品| 婷婷激情图片久久| 国产成人1区| 91精品国产经典在线观看| 欧美精选一区二区三区| 九九九精品视频| 中文一区一区三区免费在线观| 免费高潮视频95在线观看网站| 国产精品v日韩精品v欧美精品网站| 视频一区中文字幕国产| 久久在线电影| 亚洲天堂av影院| 麻豆免费精品视频| 久久狠狠久久| 亚洲日本国产| 国产一区二区高清| 99免费精品| 午夜久久中文| 韩日一区二区| 国产精品国码视频| 日韩av不卡在线观看| 国产二区精品| 久久伦理在线| 99精品视频精品精品视频| 精品视频网站| 国产精品亚洲综合色区韩国| 日韩不卡一区二区| 无码日韩精品一区二区免费| 亚洲欧美视频一区二区三区| 国产综合色产| 欧美va天堂在线| 久久精品青草| 激情综合网址| 欧美+日本+国产+在线a∨观看| 香蕉成人av| 国产亚洲一区二区手机在线观看 | 欧美亚洲一区二区三区| 亚洲一区二区日韩| 亚洲免费福利一区| 日韩一区二区三区免费视频| 伊人国产精品| 亚洲永久精品唐人导航网址| 亚洲人成高清| 日韩国产欧美一区二区三区| 免费久久精品视频| 精品伊人久久| av免费不卡国产观看| 日韩国产专区| 亚洲二区免费| 午夜欧美视频| 亚洲一区网站| 伊人精品久久| 日本精品国产| 国产精品久久久久久妇女| 久久99精品久久久久久园产越南 | 亚洲电影在线一区二区三区| 婷婷精品视频| 欧美日韩一区二区三区视频播放| 欧美1区免费| 美女网站久久| 日韩av午夜在线观看| 国产精品亚洲一区二区在线观看| 麻豆精品视频在线| 欧美sss在线视频| 亚洲欧美成人综合| 日日夜夜免费精品视频| 日韩av二区在线播放| 久久久久97| 久久精品123| 免费高清在线一区| 国产美女亚洲精品7777 | 久草免费在线视频| 精品在线播放| 日本vs亚洲vs韩国一区三区二区| 国产精品久久久久av蜜臀| 国产精品黑丝在线播放| 欧美亚洲精品在线| 在线午夜精品| 欧美日韩18| av资源亚洲| 中文久久精品| 国产精品一线| 99免费精品| 日韩av不卡在线观看| 美女av在线免费看| 免费成人在线视频观看| 国产伦精品一区二区三区视频| 国产精品xx| 丝袜国产日韩另类美女| 国产乱码精品一区二区三区四区| 日韩av有码| 亚洲色图综合| 精品一区二区三区亚洲| 亚洲女同一区| 国产精品传媒麻豆hd| 久久一区二区三区喷水| 日本免费在线视频不卡一不卡二| xxxxx性欧美特大| 亚洲影院天堂中文av色| 日本黄色精品| 亚洲三级网站| 国产一区二区视频在线看| 性色av一区二区怡红| 久久不卡国产精品一区二区| 不卡中文字幕| 久久不见久久见中文字幕免费| 激情欧美一区| 国产高清亚洲| 国产日韩综合| 亚洲免费精品| 日韩综合在线| 日韩欧美久久| 激情婷婷亚洲| 精品久久国产一区| 一区二区国产在线| 国产精品成人a在线观看| 久久国产精品久久久久久电车| 精品久久久亚洲| 日本成人一区二区| 狠狠爱成人网| 亚洲午夜天堂|