你所不知道的MethodHandle

Method Handles

Method Hanldes是在Java 7引入的概念姻成。全限定名是java.lang.invoke.MethodHandles腋逆。在這篇文章中聂沙,我們將學(xué)會(huì)如何創(chuàng)建内颗,使用MethodHandles及它的原理袖迎。

1.介紹

Method Handles的引入是為了與已經(jīng)存在的java.lang.reflect API相配合姻报。他們分別是為了解決不同的問(wèn)題而出現(xiàn)的瞒滴。從性能角度上說(shuō)鹤耍,MethodHandle api要比反射快很多因?yàn)樵L問(wèn)檢查在創(chuàng)建的時(shí)候就已經(jīng)完成了,而不是像反射一樣等到運(yùn)行時(shí)候才檢查苟穆。但同時(shí)抄课,Method Handles比反射更難用,因?yàn)闆](méi)有列舉類中成員雳旅,獲取屬性訪問(wèn)標(biāo)志之類的機(jī)制跟磨。
另外,MethodHandles可以操作方法攒盈,更改方法參數(shù)的類型和他們的順序吱晒。而反射則沒(méi)有這些功能。
從以上角度看沦童,反射更通用仑濒,但是安全性更差,因?yàn)榭梢栽诓皇跈?quán)的情況下使用反射對(duì)象偷遗。而method Handles遵從了分享者的能力墩瞳。所以method handle是一種更低級(jí)的發(fā)現(xiàn),適配和調(diào)用方法的方式氏豌,唯一的優(yōu)點(diǎn)就是更快喉酌。所以反射更適合主流Java開(kāi)發(fā)者,而method handle更適用于對(duì)編譯和運(yùn)行性能有要求的人。

2.使用

1.要使用method handle泪电,首先需要得到Lookup般妙。這是創(chuàng)造方法,構(gòu)造函數(shù)相速,屬性的method handles的工廠類碟渺。

// public方法的Lookup
MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();
// 所有方法的Lookup
MethodHandles.Lookup lookup = MethodHandles.lookup();

2.要?jiǎng)?chuàng)建MethodHandle,lookup需要一個(gè)定義了它的類型的MethodType對(duì)象突诬。這里的類型包括了傳入?yún)?shù)的類型苫拍,和最后返回的類型,要一一對(duì)應(yīng)旺隙。第一個(gè)是返回類型绒极,如果沒(méi)有返回值就是Void.class, 后面是可變的傳入?yún)?shù)的類型。

a MethodType represents the arguments and return type accepted and returned by a method handle or passed and expected by a method handle caller.

例如

// 接收數(shù)組蔬捷,返回一個(gè)List對(duì)象
MethodType mt = MethodType.methodType(List.class, Object[].class);

3.查找MethodHandle
Lookup之所以叫Lookup自然是因?yàn)樗麄冇胁檎襇ethodHandle的能力垄提。先看看他的方法。


image.png

4.接下來(lái)就可以進(jìn)行查找并調(diào)用了

MethodType mt = MethodType.methodType(String.class, char.class, char.class);
MethodHandle replaceMH = publicLookup.findVirtual(String.class, "replace", mt);
 
String output = (String) replaceMH.invoke("jovo", Character.valueOf('o'), 'a');

5.方法調(diào)用細(xì)則:
有三種方法可以調(diào)用方法invoke(), invokeWithArugments()和invokeExact()周拐,當(dāng)我們使用invoke時(shí)铡俐,我們必須固定arguments的數(shù)目。

// invoke使用
MethodType mt = MethodType.methodType(String.class, char.class, char.class);
MethodHandle replaceMH = publicLookup.findVirtual(String.class, "replace", mt);
String output = (String) replaceMH.invoke("jovo", Character.valueOf('o'), 'a');

// invokeWithArguments使用
MethodType mt = MethodType.methodType(List.class, Object[].class);
MethodHandle asList = publicLookup.findStatic(Arrays.class, "asList", mt);
List<Integer> list = (List<Integer>) asList.invokeWithArguments(1,2);

// invokeExact
MethodType mt = MethodType.methodType(int.class, int.class, int.class);
MethodHandle sumMH = lookup.findStatic(Integer.class, "sum", mt);
int sum = (int) sumMH.invokeExact(1, 11);

具體的區(qū)別是:

與invokeExact方法不同速妖,invoke方法允許更加松散的調(diào)用方式。它會(huì)嘗試在調(diào)用的時(shí)候進(jìn)行返回值和參數(shù)類型的轉(zhuǎn)換工作聪黎。這是通過(guò)MethodHandle類的asType方法來(lái)完成的罕容,asType方法的作用是把當(dāng)前方法句柄適配到新的MethodType上面,并產(chǎn)生一個(gè)新的方法句柄稿饰。當(dāng)方法句柄在調(diào)用時(shí)的類型與其聲明的類型完全一致的時(shí)候锦秒,調(diào)用invoke方法等于調(diào)用invokeExact方法;否則喉镰,invoke方法會(huì)先調(diào)用asType方法來(lái)嘗試適配到調(diào)用時(shí)的類型旅择。如果適配成功,則可以繼續(xù)調(diào)用侣姆。否則會(huì)拋出相關(guān)的異常生真。這種靈活的適配機(jī)制,使invoke方法成為在絕大多數(shù)情況下都應(yīng)該使用的方法句柄調(diào)用方式捺宗。

參考:
https://www.baeldung.com/java-method-handles
https://www.cnblogs.com/night-wind/p/4405564.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柱蟀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蚜厉,更是在濱河造成了極大的恐慌长已,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異术瓮,居然都是意外死亡康聂,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)胞四,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)恬汁,“玉大人,你說(shuō)我怎么就攤上這事撬讽∪锪” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵游昼,是天一觀的道長(zhǎng)甘苍。 經(jīng)常有香客問(wèn)我,道長(zhǎng)烘豌,這世上最難降的妖魔是什么载庭? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮廊佩,結(jié)果婚禮上囚聚,老公的妹妹穿的比我還像新娘。我一直安慰自己标锄,他們只是感情好顽铸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著料皇,像睡著了一般谓松。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上践剂,一...
    開(kāi)封第一講書(shū)人閱讀 50,084評(píng)論 1 291
  • 那天鬼譬,我揣著相機(jī)與錄音,去河邊找鬼逊脯。 笑死优质,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的军洼。 我是一名探鬼主播巩螃,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼匕争!你這毒婦竟也來(lái)了牺六?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤汗捡,失蹤者是張志新(化名)和其女友劉穎淑际,沒(méi)想到半個(gè)月后畏纲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡春缕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年盗胀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锄贼。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡票灰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宅荤,到底是詐尸還是另有隱情屑迂,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布冯键,位于F島的核電站惹盼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惫确。R本人自食惡果不足惜手报,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望改化。 院中可真熱鬧掩蛤,春花似錦、人聲如沸陈肛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)句旱。三九已至阳藻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間前翎,已是汗流浹背稚配。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工畅涂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留港华,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓午衰,卻偏偏與公主長(zhǎng)得像立宜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子臊岸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容