java的MethodHandle類詳解


一.總述

  java7為間接調用方法提供了MethodHandle類,即方法句柄。可以將其看作是反射的另一種方式。

這是使用MethodHandle調用方法的一個例子:

public class Test {
  public static void main(String[] args) throws Throwable  {
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodType mt = MethodType.methodType(String.class,char.class,char.class);
    try {
      MethodHandle mh = lookup.findVirtual(String.class,"replace", mt);
      String handled_str = (String) mh.invoke("abc",'a','c');
      System.out.print(handled_str);
    } catch (NoSuchMethodException | IllegalAccessException e) {
      e.printStackTrace();
    }
  }
}    

  用MethodHandle調用方法的流程為:

  • (1) 創建MethodType,獲取指定方法的簽名
  • (2) 在Lookup中查找MethodType的方法句柄MethodHandle
  • (3) 傳入方法參數通過MethodHandle調用方法

二.MethodType

MethodType表示一個方法類型的對象,每個MethodHandle都有一個MethodType實例,MethodType用來指明方法的返回類型和參數類型。其有多個工廠方法的重載。
static MethodType	methodType(Class<?> rtype)

static MethodType	methodType(Class<?> rtype, Class<?> ptype0)

static MethodType	methodType(Class<?> rtype, Class<?>[] ptypes)

static MethodType	methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes)

static MethodType	methodType(Class<?> rtype, List<Class<?>> ptypes)

static MethodType	methodType(Class<?> rtype, MethodType ptypes)

如上面示例代碼中的
MethodType mt = MethodType.methodType(String.class,char.class,char.class);就得到了一個方法的參數類型為char,char,返回類型為String的MethodType。

三.Lookup

  MethodHandle.Lookup可以通過相應的findxxx方法得到相應的MethodHandle,相當於MethodHandle的工廠方法。查找對象上的工廠方法對應於方法、構造函數和字段的所有主要用例。下面是官方API文檔對findxxx的說明,這些工廠方法和結果方法處理的行為之間的對應關系:

可以看出findStatic相當於得到的是一個static方法的句柄,findVirtual找的是普通方法。其他的可以從官方文檔中閱讀得知,這里不詳細說明了。

四. MethodHandle

  MethodHandle是什么?簡單的說就是方法句柄,通過這個句柄可以調用相應的方法。官方文檔對其的解釋為:

“ A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values. These transformations are quite general, and include such patterns as conversion, insertion, deletion, and substitution.”

翻譯如下:

方法句柄是對底層方法、構造函數、字段或類似低級操作的類型化、直接可執行的引用,具有參數或返回值的可選轉換。這些轉換非常普遍,包括轉換、插入、刪除和替換等模式

常用的方法為invokexxx,如下圖

  其中需要注意的是invokeinvokeExact,前者在調用的時候可以進行返回值和參數的類型轉換工作,而后者是精確匹配的。比如,在MethodType中指定的參數類型是int,如果你用invoke調用時指定的參數是Integer類型,方法調用是可以運行的,這是通過MethodHandle類的astype方法產生一個新的方法句柄。而如果用的是invokeExact則在運行時會報錯。
  另外一個需要注意的是invokexxx的所有方法返回的是Object,調用時若有返回結果一般需進行強制類型轉換。
  最后還有一點,如果調用的方法沒有返回值,那么在MethodType的工廠方法中的返回值類型寫為void.class


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM