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