java - 使用lambda表達(dá)式(匿名內(nèi)部類)傳參是否有性能問題?
問題描述
編程有一條原則如下:
避免創(chuàng)建不必要的對象:最好能重用對象,而不要在每次需要的時候就創(chuàng)建一個相同功能的新對象。
請看如下代碼:
List<String> names = Arrays.asList('peter', 'anna', 'mike', 'xenia'); // 1、匿名內(nèi)部類Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) {return b.compareTo(a); }});//2、lambda表達(dá)式Collections.sort(names, (a, b) -> b.compareTo(a));
是不是每次排序都創(chuàng)建了一個新的Comparator對象,導(dǎo)致性能降低?那么還主張使用Lambda表達(dá)式嗎?
問題解答
回答1:首先回答你的問題:是不是每次排序都創(chuàng)建了一個新的Comparator對象,導(dǎo)致性能降低?那么還主張使用Lambda表達(dá)式嗎?不是,主張
根本原因Lamdba表示根本就不是匿名內(nèi)部類的語法糖,也就是說Lambda表達(dá)式底層實現(xiàn)不是匿名內(nèi)部類的實現(xiàn)方式,他們其實兩個東西
怎么證明呢? 匿名內(nèi)部類其實在編譯的時候會生成一個類文件,命名以ClassName$數(shù)字的方式,所以要是Lamdba表達(dá)式底層也是由匿名內(nèi)部類的方式實現(xiàn)的話,那肯定也會生成一個同樣類似的內(nèi)文件 所以我們簡單把你的例子分別寫在不同包下面的類,再在來檢查編譯后的效果 匿名內(nèi)部類實現(xiàn) InnerTest
這是class文件,可以看到有兩個

lambda表達(dá)式 LamdbaTest

然而class文件只有一個
所以真相只有一個,哈哈,很顯然,這根本就不是一個東西嘛
那Lamdba表達(dá)式是怎么實現(xiàn)的? 我們可以來看看他們的字節(jié)碼,這樣骨子里的不一樣就完全展示出來了 InnerTest
LamdbaTest

可以看到兩者使用的指令都是不一樣的,Lamdba表達(dá)式在解析時,使用的是Java7新增的invokedynamic指令,如果你熟悉你這個指令的話,那就可能瞬間明白了,不熟悉的話,你可以問問度娘 不過你可以直接從這個指令名字體會出:動態(tài)調(diào)用 因此,其實不同于匿名內(nèi)部類被編譯成一個類文件,Lamdba表達(dá)式是被編譯成了一個靜態(tài)方法,我們-p可以再看一次就知道了,生成的方法名叫l(wèi)ambda$main$0

所以結(jié)合之前兩個反編譯的結(jié)果可以看到,lamdba表達(dá)式運行整體思路大致如下 1. lamdba表達(dá)式被編譯生成當(dāng)前類的一個私有靜態(tài)方法 2. 在原調(diào)用Lamdba方法的地方編譯成了一個invokedynamic指令調(diào)用,同時呢也生成了一個對應(yīng)的BootstrapMethod 3. 當(dāng)lamdba表達(dá)式被JVM執(zhí)行,也就是碰到2中說到的invokedynamic指令,該指令引導(dǎo)調(diào)用LambdaMetafactory.metafactory方法,該方法返回一個CallSite實例 4. 而這個CallSite實例中的target對象,也就是直接引用到一個MethodHandle實例,而這個MethodHandle實例會調(diào)用到1中生成的靜態(tài)方法,在上面的例子就是`lambda$main$0`這個方法,完成整個lamdba表達(dá)式的使用
再說一句 其實可以看到lamdba表達(dá)式在某種意義上的確比匿名內(nèi)部類好很多,無論是性能,可讀性還是大勢~哈哈,我要說大勢,是因為lamdba表達(dá)式后續(xù)可以優(yōu)化的空間更廣,反正我是在java中用慣了,相當(dāng)喜歡
回答2:每次排序并不會創(chuàng)建一個新的 Comparator 對象,一般情況下 Lambda 表達(dá)式對應(yīng)的實例(instance)一旦在內(nèi)存中產(chǎn)生,那么 JVM 在當(dāng)前環(huán)境下會重復(fù)使用這個實例。具體的說明,可以參考這個鏈接:Run-Time Evaluation of Lambda Expressions
在可以提升程序可讀性和開發(fā)效率的前提下,主張使用 Lambda 表達(dá)式
回答3:可以靜態(tài)聲明一個Lambda表達(dá)式內(nèi)部匿名類對象;
朝生夕滅的小對象對JVM來說不是大問題;
相關(guān)文章:
1. 我在centos容器里安裝docker,也就是在容器里安裝容器,報錯了?2. 在windows下安裝docker Toolbox 啟動Docker Quickstart Terminal 失敗!3. docker-compose中volumes的問題4. docker不顯示端口映射呢?5. golang - 用IDE看docker源碼時的小問題6. docker內(nèi)創(chuàng)建jenkins訪問另一個容器下的服務(wù)器問題7. 關(guān)docker hub上有些鏡像的tag被標(biāo)記““This image has vulnerabilities””8. javascript - 最近用echarts做統(tǒng)計圖時遇到兩個問題!!9. javascript - 連續(xù)點擊觸發(fā)mouseleave事件10. mac里的docker如何命令行開啟呢?

網(wǎng)公網(wǎng)安備