国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
java為什么匿名內(nèi)部類的參數(shù)引用時final(轉(zhuǎn))

https://blog.csdn.net/z69183787/article/details/68490440

 

https://www.zhihu.com/question/21395848

https://www.zhihu.com/question/24084277/answer/110176733

喜歡看生肉的同學(xué)就不用看我的回答了,直接看R大的三篇回答,尤其是第一篇后面的回復(fù)部分。

我只是試著用大白話做個簡單的整理,希望能更容易理解一點。

關(guān)于對象與閉包的關(guān)系的一個有趣小故事 (這篇的精華在后面的回復(fù),小故事可以跳過)

JVM的規(guī)范中允許編程語言語義中創(chuàng)建閉包(closure)嗎? - RednaxelaFX 的回答

為什么Java閉包不能通過返回值之外的方式向外傳遞值? - RednaxelaFX 的回答

1. 閉包(Closure)
什么是閉包,大白話不怎么嚴(yán)謹(jǐn)?shù)恼f就是:

 

  1. 一個依賴于外部環(huán)境自由變量的函數(shù)
  2. 這個函數(shù)能夠訪問外部環(huán)境里的自由變量

看下面這個Javascript閉包的例子:

 


對內(nèi)部函數(shù)function(x)來講,y就是自由變量,而且function(x)的返回值,依賴于這個外部自由變量

y。而往上推一層,外圍Add(y)函數(shù)正好就是那個包含自由變量y的環(huán)境。而且Javascript的語法允

許內(nèi)部函數(shù)function(x)訪問外部函數(shù)Add(y)的局部變量。滿足這三個條件,所以這個時候,外部函

數(shù)Add(y)對內(nèi)部函數(shù)function(x)構(gòu)成了閉包。

閉包的結(jié)構(gòu),如果用λ演算表達式來寫,就是多參數(shù)的Currying技術(shù)。

>λx.λy.x+y

但在Java中我們看不到這樣的結(jié)構(gòu)。因為Java主流語法不允許這樣的直接的函數(shù)套嵌和跨域訪問變量。


2. 類和對象

但Java中真的不存在閉包嗎?正好相反,Java到處都是閉包,所以反而我們感覺不出來在使用閉

包。因為Java的“對象”其實就是一個閉包。其實無論是閉包也好,對象也好,都是一種數(shù)據(jù)封裝的

手段??聪旅孢@個類


看上去x在函數(shù)add()的作用域外面,但是通過Add類實例化的過程,變量”x“和數(shù)值”2“之間已經(jīng)綁

定了,而且和函數(shù)add()也已經(jīng)打包在一起。add()函數(shù)其實是透過this關(guān)鍵字來訪問對象的成員字

段的。

如果對閉包有疑問,可以看這個更詳細的回答:

閉包(計算機科學(xué))是什么? - 胖胖的回答


3. Java內(nèi)部類是閉包:包含指向外部類的指針

那Java里有沒有除了實例對象之外的閉包結(jié)構(gòu)?Java中的內(nèi)部類就是一個典型的閉包結(jié)構(gòu)。例子如下,


下圖畫的就是上面代碼的結(jié)構(gòu)。內(nèi)部類(Inner Class)通過包含一個指向外部類的引用,做到自

由訪問外部環(huán)境類的所有字段,變相把環(huán)境中的自由變量封裝到函數(shù)里,形成一個閉包。



4. 別扭的匿名內(nèi)部類

但Java匿名內(nèi)部類就做得比較尷尬。下面這個例子中,getAnnoInner負(fù)責(zé)返回一個匿名內(nèi)部類的引用。


匿名內(nèi)部類因為是匿名,所以不能顯式地聲明構(gòu)造函數(shù),也不能往構(gòu)造函數(shù)里傳參數(shù)。不但返回的只是個叫AnnoInner的接口,而且還沒有和它外圍環(huán)境getAnnoInner()方法的局部變量x和y構(gòu)成任何類的結(jié)構(gòu)。但它的addXYZ()函數(shù)卻直接使用了x和y這兩個自由變量來計算結(jié)果。這就說明,外部方法getAnnoInner()事實上已經(jīng)對內(nèi)部類AnnoInner構(gòu)成了一個閉包。

但這里別扭的地方是這兩個x和y都必須用final修飾,不可以修改。如果用一個changeY()函數(shù)試圖修改外部getAnnoInner()函數(shù)的成員變量y,編譯器通不過,

error: cannot assign a value to final variable y

這是為什么呢?因為這里Java編譯器支持了閉包,但支持地不完整。說支持了閉包,是因為編譯器編譯的時候其實悄悄對函數(shù)做了手腳,偷偷把外部環(huán)境方法的x和y局部變量,拷貝了一份到匿名內(nèi)部類里。如下面的代碼所示。


所以用R大回答里的原話說就是:

Java編譯器實現(xiàn)的只是capture-by-value,并沒有實現(xiàn)capture-by-reference。

而只有后者才能保持匿名內(nèi)部類和外部環(huán)境局部變量保持同步。

但Java又不肯明說,只能粗暴地一刀切,就說既然內(nèi)外不能同步,那就不許大家改外圍的局部變量。


5. 其他和匿名內(nèi)部類相似的結(jié)構(gòu)

《Think in Java》書里,只點出了匿名內(nèi)部類來自外部閉包環(huán)境的自由變量必須是final的。但實際上,其他幾種不太常用的內(nèi)部類形式,也都有這個特性。

比如在外部類成員方法內(nèi)部的內(nèi)部類。


比如在一個代碼塊block里的內(nèi)部類。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
深入理解JVM內(nèi)幕:從基本結(jié)構(gòu)到Java 7新特性
Java的局部內(nèi)部類以及final類型的參數(shù)和變量
Java中的匿名內(nèi)部類:由setOnClickListener說起
Java中this關(guān)鍵字的使用
java中this關(guān)鍵字的作用
深入理解Java中為什么內(nèi)部類可以訪問外部類的成員
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服