深入理解JAVA虛擬機學習筆記15——字節碼執行引擎(動態類型語言與lambda表達式)

每天進步一點點!

在我們剛接觸Java時候,我們就被告知,Java是一門靜態類型語言。

隨着開發技術的發展,出現了更多的動態語言,比如我們耳熟能詳的Groovy,List,Python,Ruby,JavaScript等。

這也就迫使Java需要做出改變,從jdk7開始,Java提供了對動態類型語言的支持,引入了invokedymanic指令提供對動態類型語言的支持。

隨之在jdk8開始,推出了lambda表達式,來實現動態類型語言特性。

動態類型語言這個詞已經活躍了很多年了,聽起來比較複雜,其實也挺複雜的。

首先我們看一下什麼是動態類型語言?簡單地說,靜態類型語言在編譯期進行類型檢查,而動態類型語言在運行期進行類型檢查。

動態類型語言的特點,說的再直白一點——“變量無類型而變量值纔有類型”。

如下圖所示,在Java方法中,定義的變量a,b,c的類型是確定的,就是int型。

下面我們再看一下JavaScript的代碼,如果不通過執行的話,我們是無法確定element到底是什麼類型的。

知道了兩種類型的區別,再簡單對比一下兩種類型的優缺點:

靜態類型語言:提供嚴謹的類型檢查,有利於穩定性和功能擴展,適合大型系統。

動態類型語言:代碼編寫更加靈活,開發效率提升。

既然提到了lambda表達式,那就讓我們簡單地一起來學習一下。

lambda表達式的語法格式:(parameters) -> expression或(parameters) ->{ statements; }。

用法和一些需要注意的地方,我們通過下面幾個例子感受一下。

1. lambda表達式可以用來代替匿名內部類

如下圖所示,我們寫了一個test1()方法,用來創建一個線程,線程中包含一個打印操作。

我們便可以使用test2()中一行代碼作爲代替,你還別說,確實些起來更加簡潔了!

注意了,我們可以看到,這裏參數列表爲空,lambda表達式是可以沒有參數的!

還有一個地方,那就是如果主題包含了一個語句就不用寫花括號{}了。

前面我們說過,引入了invokedymanic指令提供對動態類型語言的支持,我們不妨打開字節碼文件看一眼,嗯,還好書上沒有騙我。

相對應地,常量池中的類型也變成了CONSTANT_Methodref_info。

2. lambda表達式可以用來實現接口

首先我們定義一個接口Inter,其中包含一個方法sayHello(),需要傳入參數name。

按照常規的做法,我們會寫一個實現類InterImpl用來實現Inter接口,並實現sayHello()方法。

然後通過創建對象,傳入參數,調用方法。

但是,假如使用lambda表達式怎麼寫呢?如下圖所示,簡單的令人髮指有木有!!!

好,這裏有第三個需要注意的地方了:當參數只有一個的時候,可以不用寫括號。

3. lambda表達式實現集合的遍歷

這個相信朋友都能看懂就不說什麼了,但是有一點前面已經提到過了,大家不要忽視了,參數str是沒有指定類型的。

4. 使用lambda表達式實現函數式編程

在Java 8中新增了一個類java.util.function.Predicate是支持函數式編程的。

最後要注意的一點:主體只有一個表達式編譯器會自動返回值,不需要寫return,但是多條的時候是需要的。

看了這麼多lambda表達式的例子,我們再來看一下書中提到了一種新的確定目標方法的類java.lang.invoke.MethodHandle:

我們打開看一眼,一共1457行,這一片一片的都是啥啊?幸虧筆者眼尖,在248行發現了“Usage examples”幾個大字,ctrl+c,ctrl+v複製到單元測試類中,就看一下前幾行吧。

mt中包含了方法的返回值類型(String)和參數類型數組。

mh中又增加member用來存儲對應的目標方法和執行指令:java.lang.String.replace(char,char)String/invokeSpecial

最後在invokeExact中調用了方法的執行,筆者這裏也只有拋磚引入,更加深入的使用方法,還有待於朋友們共同探討。

最後,依據筆者的經驗,動態類型語言可以用來寫工具類。

however,然鵝,並不建議在業務系統代碼中使用,可讀性真的有待商榷。

喜歡文章或想一起學習的朋友可以關注我,給我點贊,我將會持續更新,有什麼疑問或文中有不當之處請給我留言,真誠地希望能與大家一起交流探討,學習進步!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章