java7 MethodHandle學習筆記

簡介

java7在JSR 292中增加了對動態類型語言的支持,使java也可以像C語言那樣將方法作爲參數傳遞,其實現在lava.lang.invoke包中。MethodHandle作用類似於反射中的Method類,但它比Method類要更加靈活和輕量級。通過MethodHandle進行方法調用一般需要以下幾步:

(1)創建MethodType對象,指定方法的簽名;

(2)在MethodHandles.Lookup中查找類型爲MethodType的MethodHandle;

(3)傳入方法參數並調用MethodHandle.invoke或者MethodHandle.invokeExact方法。


MethodType

可以通過MethodHandle類的type方法查看其類型,返回值是MethodType類的對象。也可以在得到MethodType對象之後,調用MethodHandle.asType(mt)方法適配得到MethodHandle對象。可以通過調用MethodType的靜態方法創建MethodType實例,有三種創建方式:

(1)methodType及其重載方法:需要指定返回值類型以及0到多個參數;

(2)genericMethodType:需要指定參數的個數,類型都爲Object;

(3)fromMethodDescriptorString:通過方法描述來創建。

創建好MethodType對象後,還可以對其進行修改,MethodType類中提供了一系列的修改方法,比如:changeParameterType、changeReturnType等。


Lookup

MethodHandle.Lookup相當於MethodHandle工廠類,通過findxxx方法可以得到相應的MethodHandle,還可以配合反射API創建MethodHandle,對應的方法有unreflect、unreflectSpecial等。


invoke

在得到MethodHandle後就可以進行方法調用了,有三種調用形式:

(1)invokeExact:調用此方法與直接調用底層方法一樣,需要做到參數類型精確匹配;

(2)invoke:參數類型鬆散匹配,通過asType自動適配;

(3)invokeWithArguments:直接通過方法參數來調用。其實現是先通過genericMethodType方法得到MethodType,再通過MethodHandle的asType轉換後得到一個新的MethodHandle,最後通過MethodHandle的invokeExact方法來完成調用。


附MethodHandle作爲參數的示例代碼:

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Arrays;
import java.util.List;
public class MethodHandleTest {
    public static void main(String[] args) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle mh = lookup.findStatic(MethodHandleTest.class, "doubleVal", MethodType.methodType(int.class, int.class));
        List<Integer> dataList = Arrays.asList(1, 2, 3, 4, 5);
        MethodHandleTest.transform(dataList, mh);// 方法做爲參數
        for (Integer data : dataList) {
            System.out.println(data);//2,4,6,8,10
        }
    }
    public static List<Integer> transform(List<Integer> dataList, MethodHandle handle) throws Throwable {
        for (int i = 0; i < dataList.size(); i++) {
            dataList.set(i, (Integer) handle.invoke(dataList.get(i)));//invoke
        }
        return dataList;
    }
    public static int doubleVal(int val) {
        return val * 2;
    }
}

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