lambda運算式和閉包

來源:互聯網
上載者:User

標籤:new   ext   對象   word   turn   它的   文法糖   ++   blank   

區分lambda運算式和閉包

熟悉的Javascript或者Ruby的同學,可能對另一個名詞:閉包更加熟悉。因為一般閉包的範例程式碼,長得跟lambda差不多,導致我也在以前很長一段時間對這兩個概念傻傻分不清楚。其實呢,這兩個概念是完全不同維度東西。

閉包是個什麼東西呢?我覺得Ruby之父松本行弘在《代碼的未來》一書中解釋的最好:閉包就是把函數以及變數包起來,使得變數的生存周期延長。閉包跟物件導向是一棵樹上的兩條枝,實現的功能是等價的。

這樣說可能不夠直觀,我們還是用代碼說話吧。其實Java在很早的版本就支援閉包了,只是因為應用情境太少,這個概念一直沒得到推廣。在Java6裡,我們可以這樣寫:

public static Supplier<Integer> testClosure(){ final int i = 1; return new Supplier<Integer>() { @Override public Integer get() { return i; } };}public interface Supplier<T> { T get();}

看出問題了嗎?這裡i是函數testClosure的內部變數,但是最終返回裡的匿名對象裡,仍然返回了i。我們知道,函數的局部變數,其範圍僅限於函數內部,在函數結束時,就應該是不可見狀態,而閉包則將i的生存周期延長了,並且使得變數可以被外部函數所引用。這就是閉包了。這裡,其實我們的lambda運算式還沒有出現呢!

而支援lambda運算式的語言,一般也會附帶著支援閉包了,因為lambda總歸在函數內部,與函數局部變數屬於同一語句塊,如果不讓它引用局部變數,不會讓人很彆扭嗎?例如Python的lambda定義我覺得是最符合λ運算元的形式的,我們可以這樣定義lambda:

#!/usr/bin/pythony = 1f=lambda x: x + yprint f(2)y = 3print f(2)輸出: 35

 

這裡y其實是外部變數。

Java中閉包帶來的問題

在Java的經典著作《Effective Java》、《Java Concurrency in Practice》裡,大神們都提到:匿名函數裡的變數引用,也叫做變數引用泄露,會導致安全執行緒問題,因此在Java8之前,如果在匿名類內部引用函數局部變數,必須將其聲明為final,即不可變對象。(Python和Javascript從一開始就是為單線程而生的語言,一般也不會考慮這樣的問題,所以它的外部變數是可以任意修改的)。

在Java8裡,有了一些改動,現在我們可以這樣寫lambda或者匿名類了:

public static Supplier<Integer> testClosure() { int i = 1; return () -> { return i; };}

這裡我們不用寫final了!但是,Java大神們說的引用泄露怎麼辦呢?其實呢,本質沒有變,只是Java8這裡加了一個文法糖:在lambda運算式以及匿名類內部,如果引用某局部變數,則直接將其視為final。我們直接看一段代碼吧:

public static Supplier<Integer> testClosure() { int i = 1; i++; return () -> { return i; //這裡會出現編譯錯誤 };}

明白了嗎?其實這裡我們僅僅是省去了變數的final定義,這裡i會強制被理解成final類型。很搞笑的是編譯錯誤出現在lambda運算式內部引用i的地方,而不是改變變數值的i++…這也是Java的lambda的一個被人詬病的地方。我只能說,強制閉包裡變數必須為final,出於嚴謹性我還可以接受,但是這個文法糖有點酸酸的感覺,還不如強制寫final呢…

 

lambda運算式和閉包

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.