lambda里面赋值局部变量必须是final原因
如上代碼,lambda里面要訪問局部變量會報如照片錯誤:
在介紹為什么會報錯的原因之前,稍作先介紹什么Lambda表達式
一、什么是lambda表達式
在java8實戰這本書中,將Lambda表達式解釋為:可傳遞的匿名函數的一種方式:它沒有名稱,但他有參數列表、函數主體、返回類型,可能還有一個可以拋出的異常列表
二、在哪里使用Lambda表達式
1.函數式接口:只定義了一個抽象方法的接口
2.函數描述符:函數式接口的抽象方法的簽名基本上就是Lambda表達式的簽名,這個抽象方法叫做函數描述符
三、函數式接口可以干什么?
lambda表達式可以以內聯的形式為接口的抽象方法提供實現,并把整個表達式作為函數式接口的實例即創建一個函數式接口的實例
四、為什么lambda里面要訪問局部變量必須是final
現在再來解釋為什么lambda里面要訪問局部變量必須是final?
首先:lambda表示可以無限制捕獲實例變量(即表達式主體中的引用)和靜態變量
但是,局部變量必須是顯示聲明為final或事實上是final
那么這lambda里面要賦值局部變量必須是final有什么關系?
實例變量:存儲在堆中
局部變量:則保存在棧上
lambda表達式以內聯的形式創建一個函數式接口的實例,保存在堆中,而局部變量則保存在棧中,可能造成實例對象得生命周期很有可能超過局部變量得生命周期:
1.局部變量聲明周期:當該方法被調用時,該方法中的局部變量在棧中被創建。當方法調用結束時,退棧,這些局部變量全部死亡。而函數式接口實例對象生命周期和其他類對象一樣:自創建一個實例對象,系統為該對象分配內存,直到沒有引用變量指向分配給該對象得內存,它被JVM垃圾回收,所以完全可能出現的一種情況是:方法已調用結束,局部變量已死亡,但實例對象的對象仍然活著。
2.如果實例對象訪問了同一個方法中得局部變量,就要求只要實例對象還活著,那么棧中的那些它要所訪問的局部變量就不能死亡
因為創建一個函數式接口實例實際也是創建一個匿名內部類,這里是從匿名內部類的角度分析
以下是《java8實戰》解釋:
1.Lambda可以直接訪問局部變量,而且Lambda是在一個線程中使用的,則使用Lambda的線程,可能會在分配該變量的線程將這個變量收回之后,去訪問該變量。因此,Java在訪問自由局部變量時,實際上是在訪問它的副本,而不是訪問原始變量。
2.這一限制不鼓勵你使用改變外部變量的典型命令式編程模式
五、lambda里面要賦值局部變量而不使用final
則局部變量使用=》引用類型
屬于個人理解,有不對的地方也請指出。
總結
以上是生活随笔為你收集整理的lambda里面赋值局部变量必须是final原因的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员法律考试(6)-民法(3)
- 下一篇: erlang精要(19)-以函数作为参数