日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lambda表达式和闭包Closure

發布時間:2024/2/28 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lambda表达式和闭包Closure 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 簡介
  • JS中的閉包
  • java中的閉包
  • 深入理解lambda表達式和函數的局部變量
  • 總結

簡介

我們通常講到閉包,一般都是指在javascript的環境中。閉包是JS中一個非常重要的也非常常用的概念。閉包產生的原因就是變量的作用域范圍不同。一般來說函數內部的定義的變量只有函數內部可見。如果我們想要在函數外部操作這個變量就需要用到閉包了。

更多精彩內容且看:

  • 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
  • java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程

更多內容請訪問www.flydean.com

JS中的閉包

在JS中,變量可以分為兩種全局作用域和局部作用域。在函數外部無法讀取函數內部定義的局部變量。

  function f1(){var n=10;}   alert(n); // error

上面的例子中,我們在函數f1中定義了一個局部變量n,然后嘗試從函數外部訪問它。結果出錯。

雖然函數中定義的變量在函數外部無法被訪問。但是在函數中定義的函數中可以訪問呀。

function f1(){var n=10;function f2(){       alert(n);}return f2;}var result=f1();   result(); // 10

上面的例子中,我們在f1中定義了f2,在f2中訪問了局部變量n。最后將f2返回。接著我們可以操作返回的函數f2來對函數中定義的局部變量n進行操作。

所以我們得出了閉包的定義:閉包就是定義在函數內部的函數,或者閉包是能夠訪問函數局部變量的函數。

java中的閉包

在lambda表達式出現之前,java中是沒有函數的概念的。和函數差不多相當的就是方法了。

在方法內部可以定義方法的局部變量。我們無法在方法內部定義方法,但是我們可以在方法內部定義匿名類。那么這個匿名類是可以訪問方法中定義的局部變量的。如下例所示:

public Runnable createClosureUsingClass(){int count=10;Runnable runnable= new Runnable() {@Overridepublic void run() {System.out.println(count);}};return runnable;}

在上面的方法中,我們定義了一個局部變量count。然后創建了一個匿名類runnable。在runnable中,我們訪問了局部變量count。

最后將這個創建的匿名類返回。這樣返回的匿名類就包含了對方法局部變量的操作,這樣就叫做閉包。

在Lambda表達式最佳實踐中,我們介紹了lambda表達式和匿名類的不同之處在于:

在內部類中,會創建一個新的作用域范圍,在這個作用域范圍之內,你可以定義新的變量,并且可以用this引用它。

但是在Lambda表達式中,并沒有定義新的作用域范圍,如果在Lambda表達式中使用this,則指向的是外部類。

雖然this的指向是不同的,但是在lambda表達式中也是可以訪問方法的局部變量:

public Runnable createClosureUsingLambda(){int count=10;Runnable runnable=()-> System.out.println(count);return runnable;}

上面的例子中,我們在lambda表達式中訪問了定義的count變量。

深入理解lambda表達式和函數的局部變量

首先lambda表達式是無狀態的,因為lambda表達式的本質是函數,它的作用就是在給定輸入參數的情況下,輸出固定的結果。

如果lambda表達式中引用的方法中的局部變量,則lambda表達式就變成了閉包,因為這個時候lambda表達式是有狀態的。我們接下來用個例子來具體說明。

上面的lambda表達式創建的Runnable,我們可以這樣使用:

public void testClosureLambda(){Runnable runnable=createClosureUsingLambda();runnable.run();}

為了深入理解lambda表達式和局部變量傳值的關系,我們將編譯好的class文件進行反編譯。

javap -c -p ClosureUsage

將部分輸出結果列出如下:

public java.lang.Runnable createClosureUsingLambda();Code:0: bipush 102: istore_13: iload_14: invokedynamic #12, 0 // InvokeDynamic #0:run:(I)Ljava/lang/invokedynamicinvokedynamic;9: astore_210: aload_211: areturnprivate static void lambda$createClosureUsingLambda$0(int);Code:0: getstatic #29 // Field java/lang/System.out:Ljava/io/PrintStream;3: iload_04: invokevirtual #35 // Method java/io/PrintStream.println:(I)V7: return

上面我們列出了createClosureUsingLambda和它內部的lambda表達式的反編譯結果。

可以看到在createClosureUsingLambda方法中,我們首先定義了一個值為10的int,并將其入棧。

再看lambda表達式生成的方法,我們可以看到這個方法多出了一個int參數,并且通過getstatic命令將參數傳遞進來。

這就是lambda表達式傳遞狀態的原理。

總結

本文介紹了閉包和lambda表達式之間的關系,并從字節碼的角度進一步說明了局部變量是怎么傳遞給函數內部的lambda表達式的。

本文的例子https://github.com/ddean2009/
learn-java-base-9-to-20

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/java-lambda-closure/

本文來源:flydean的博客

歡迎關注我的公眾號:程序那些事,更多精彩等著您!

總結

以上是生活随笔為你收集整理的Lambda表达式和闭包Closure的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。