0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

MethodHandle調(diào)用示例

科技綠洲 ? 來源:Java技術(shù)指北 ? 作者:Java技術(shù)指北 ? 2023-10-13 14:17 ? 次閱讀

反射(Reflect)作為Java最重要的一種機制,相信大家一定都很熟悉了,今天要介紹另一種和反射機制類似的方法調(diào)用機制——MethodHandle。

MethodHandle是Java7引入的一種機制,主要是為了JVM支持動態(tài)語言。

一個MethodHandle調(diào)用示例

首先,讓指北君給大家演示一下最基本的MethodHandle使用。

第一步:創(chuàng)建查找對象:Lookup

// 獲取Look用于查找方法句柄
  MethodHandles.Lookup lookup = MethodHandles.lookup();

第二步:創(chuàng)建方法類型:MethodType

構(gòu)造方法的返回值類型,參數(shù)類型

// 方法類型,描述返回值和參數(shù),第一個參數(shù)為返回值類型,void則為void.class。第二個參數(shù)開始為被調(diào)用方法的參數(shù)類型
  MethodType mt = MethodType.methodType(boolean.class, String.class, int.class);

第三步:查找方法句柄

Lookup的findVirtual查找成員方法

//查找方法句柄,參數(shù)1:調(diào)用類,參數(shù)2:方法名,參數(shù)3:方法類型
  MethodHandle handle = lookup.findVirtual(String.class, "startsWith", mt);

第四步:方法調(diào)用

通過MehodHandle的invoke方法執(zhí)行,并返回結(jié)果

//方法調(diào)用,參數(shù)1:實例,參數(shù)2..n:方法參數(shù)
  Boolean value = (Boolean)handle.invoke("the i am in the room", "the", 0);

以上就是一個簡單的調(diào)用示例。

核心代碼解讀

上面我們展示了一個最進本MethodHandle方式的方法調(diào)用,下面我們將對其中用到的主要類進行介紹。這些主要的類包含MethodType,MethodHandle,MethodHandles及Lookup。

MethodType

首先,我們來看看Methodtype,MethodType是用來封裝方法輸入輸出類型的,包含方法的返回和方法的參數(shù)。MethodType構(gòu)造方法為私有,只能通過MethodType提供的靜態(tài)工具方法來獲取實例

/**
     * Constructor that performs no copying or validation.
     * Should only be called from the factory method makeImpl
     */
    private MethodType(Class< ? > rtype, Class< ? >[] ptypes) {
        this.rtype = rtype;
        this.ptypes = ptypes;
    }

MethodType中常用的工具方法有:

  • 大于一個參數(shù)
public static MethodType methodType(Class< ? > rtype, Class< ? > ptype0, Class< ? >... ptypes) {
        Class< ? >[] ptypes1 = new Class< ? >[1+ptypes.length];
        ptypes1[0] = ptype0;
        System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
        return makeImpl(rtype, ptypes1, true);
    }
  • 無參數(shù)
public static MethodType methodType(Class< ? > rtype) {
        return makeImpl(rtype, NO_PTYPES, true);
    }

工具方法都通過makeImple方法來封裝MethodType實例,指北君帶領(lǐng)大家來看看makeImple中做了哪些事情:

  1. 參數(shù)檢查
    • 返回值的類型不能為null,如果無返回使用void.class
    • 參數(shù)類型不能為null,且不能為void.class
  2. 使用緩存表緩存MethodType實例,優(yōu)化處理
  3. 如果非信任模式(trusted==false),則克隆參數(shù)數(shù)組

這里需要注意MethodType重寫了hashCode方法,從邏輯看參數(shù)數(shù)組克隆不影響同類型的緩存機制。

static
    MethodType makeImpl(Class< ? > rtype, Class< ? >[] ptypes, boolean trusted) {
        if (ptypes.length == 0) {
            ptypes = NO_PTYPES; trusted = true;
        }
        MethodType primordialMT = new MethodType(rtype, ptypes);
        MethodType mt = internTable.get(primordialMT);
        if (mt != null)
            return mt;

        // promote the object to the Real Thing, and reprobe
        MethodType.checkRtype(rtype);
        if (trusted) {
            MethodType.checkPtypes(ptypes);
            mt = primordialMT;
        } else {
            // Make defensive copy then validate
            ptypes = Arrays.copyOf(ptypes, ptypes.length);
            MethodType.checkPtypes(ptypes);
            mt = new MethodType(rtype, ptypes);
        }
        mt.form = MethodTypeForm.findForm(mt);
        return internTable.add(mt);
    }

除了靜態(tài)工具方法外,MethodType還有幾個實例方法,主要為差異性較小的MethodType提供快速獲取實例的方法。包含:

  • changeParameterType
  • insertParameterTypes
  • appendParameterTypes
  • dropParameterTypes

MethodHandle

MethodHandle為抽象類,但是里面提供了大量的原生方法,提供底層訪問,也是方法調(diào)用的核心邏輯。這部分涉及MethodHandle的機制實現(xiàn),對于使用功能來說指北君就不在此展開了。

@HotSpotIntrinsicCandidate
    public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;

    @HotSpotIntrinsicCandidate
    public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;

圖片
調(diào)用方法

MethodHandles, Lookup

MethodHandles不是MethodHandle的實現(xiàn),他提供工具用于幫助獲取MethodHandle,我們主要使用到lookup(),publicLookup()

@CallerSensitive注解,可以使Reflection.getCallerClass()獲取到調(diào)用lookup()方法的類

@CallerSensitive
    @ForceInline // to ensure Reflection.getCallerClass optimization
    public static Lookup lookup() {
        return new Lookup(Reflection.getCallerClass());
    }
public static Lookup publicLookup() {
        return Lookup.PUBLIC_LOOKUP;
    }

Lookup構(gòu)造方法主要傳入兩個參數(shù):

  1. lookupClass搜尋的類,
  2. allowedModes:許可模式。

最后,通過Lookup的findXXX獲取到MethodHandle,詳細說明見下表:

圖片
查找方法

小結(jié)

關(guān)于MethodHandle的基本使用就基本講完,這里附上一張類圖便大家理解:圖片

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 參數(shù)
    +關(guān)注

    關(guān)注

    11

    文章

    1661

    瀏覽量

    31879
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4671

    瀏覽量

    67770
  • Method
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    7243
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    155

    瀏覽量

    12168
收藏 人收藏

    評論

    相關(guān)推薦

    gpio示例調(diào)用流程

    NuttX版本:V10.1.0MCU:STM32F411CEU6GPIO:PB8 --- LED前提知識: NuttX V10.1.0 : gpio示例調(diào)用流程_
    發(fā)表于 02-17 07:39

    求助,請問有沒有UM2262調(diào)用加密庫的具體示例?

    我的項目使用移植到我的 STM32L496 板的 SBSFU 模板。我需要從用戶應(yīng)用程序調(diào)用加密庫。UM2262 在 6.2.3 和 6.2.4 節(jié)中提到了加密中間件支持,但它是模糊的。是否有其他文檔可以更好地解釋,或者可能是從用戶應(yīng)用程序調(diào)用加密庫的具體
    發(fā)表于 12-26 06:48

    淺談C、C++ 和 ARM 匯編語言之間的調(diào)用

    之間的調(diào)用 本節(jié)提供一些示例,顯示如何從C++調(diào)用C和匯編語言代碼,以及從C和匯編語言調(diào)用 C++ 代碼。其中包括調(diào)用約定和數(shù)據(jù)類型。主要包
    發(fā)表于 10-19 09:24 ?2次下載

    python代碼示例之基于Python的日歷api調(diào)用代碼實例

    本文檔的主要內(nèi)容詳細介紹的是python代碼示例之基于Python的日歷api調(diào)用代碼實例。
    發(fā)表于 09-06 14:25 ?42次下載
    python代碼<b class='flag-5'>示例</b>之基于Python的日歷api<b class='flag-5'>調(diào)用</b>代碼實例

    API-Shop-OCR-營業(yè)執(zhí)照識別API接口Python調(diào)用示例代碼說明

    本文檔的主要內(nèi)容詳細介紹的是API-Shop-OCR-營業(yè)執(zhí)照識別API接口Python調(diào)用示例代碼說明
    發(fā)表于 01-10 11:48 ?6次下載
    API-Shop-OCR-營業(yè)執(zhí)照識別API接口Python<b class='flag-5'>調(diào)用</b><b class='flag-5'>示例</b>代碼說明

    設(shè)計示例

    六設(shè)計示例
    的頭像 發(fā)表于 05-29 11:10 ?1156次閱讀
    設(shè)計<b class='flag-5'>示例</b>

    Labview的異步調(diào)用示例工程文件免費下載

    本文檔的主要內(nèi)容詳細介紹的是Labview的異步調(diào)用示例vi工程文件免費下載
    發(fā)表于 10-14 08:00 ?21次下載
    Labview的異步<b class='flag-5'>調(diào)用</b><b class='flag-5'>示例</b>工程文件免費下載

    Arduino庫直接調(diào)用沒有原庫復(fù)雜調(diào)用有用的數(shù)據(jù)

    本文檔的主要內(nèi)容詳細介紹的是Arduino庫直接調(diào)用沒有原庫復(fù)雜調(diào)用有用的數(shù)據(jù)免費下載。
    發(fā)表于 03-04 08:00 ?5次下載

    華為開發(fā)者HarmonyOS零基礎(chǔ)入門:系統(tǒng)能力調(diào)用示例

    華為開發(fā)者HarmonyOS零基礎(chǔ)入門:系統(tǒng)能力調(diào)用示例,修改組件屬性頁面加載參數(shù)接收數(shù)據(jù)連接,優(yōu)化切換交互體驗。
    的頭像 發(fā)表于 10-23 10:44 ?1321次閱讀
    華為開發(fā)者HarmonyOS零基礎(chǔ)入門:系統(tǒng)能力<b class='flag-5'>調(diào)用</b><b class='flag-5'>示例</b>

    軟件示例:DA1468x 示例設(shè)置

    軟件示例:DA1468x 示例設(shè)置
    發(fā)表于 03-13 20:15 ?0次下載
    軟件<b class='flag-5'>示例</b>:DA1468x <b class='flag-5'>示例</b>設(shè)置

    SCL中調(diào)用函數(shù)的示例

    在此,可插入函數(shù) (FC) 調(diào)用和函數(shù)塊 (FB) 調(diào)用。函數(shù)塊可作為單實例、多重實例或參數(shù)實例進行調(diào)用
    的頭像 發(fā)表于 06-06 10:18 ?1881次閱讀

    軟件示例:DA1468x 示例設(shè)置

    軟件示例:DA1468x 示例設(shè)置
    發(fā)表于 07-05 18:59 ?0次下載
    軟件<b class='flag-5'>示例</b>:DA1468x <b class='flag-5'>示例</b>設(shè)置

    移動數(shù)據(jù)的編程示例

    編程示例 在此編程示例中,將移動在生產(chǎn)班次期間為示例收集的數(shù)據(jù)值以作進一步處理。收集的數(shù)據(jù)放在 ARRAY 中。通過“MOVE_BLK_VARIANT:移動塊”(Move block) 指令,可以
    的頭像 發(fā)表于 08-23 10:10 ?1152次閱讀
    移動數(shù)據(jù)的編程<b class='flag-5'>示例</b>

    reset API使用示例步驟

    時鐘和復(fù)位是兩個不同的驅(qū)動,但通常都是由負責clock驅(qū)動的人,把reset驅(qū)動完成。同樣,reset驅(qū)動也是由芯片廠商去完成的。 reset API使用示例 基本步驟: 1、調(diào)用
    的頭像 發(fā)表于 09-27 14:17 ?843次閱讀

    python調(diào)用windows命令

    Windows命令,提供一些實際的示例和代碼。 首先,我們需要了解一些基本概念。Windows命令是一種命令行界面(CLI),它允許用戶通過鍵入命令來與操作系統(tǒng)進行交互。Python提供了一個名為 subprocess 的內(nèi)置模塊,它允許我們在Python程序中執(zhí)行外部命令。 調(diào)
    的頭像 發(fā)表于 11-29 14:34 ?827次閱讀