Java MethodHandle
Java7在JSR 292中增加了對動態型別語言的支援,使得java也可以像C語言那樣將方法作為引數傳遞。
在java.lang.invoke包中MethodHandle作用類似於反射中的Method類,但它比Method類要更加靈活和輕量級。
Reflection是java api層面的反射呼叫,而MethodHandle則是jvm層面支援呼叫。因此Reflection是重量級,MethodHandle則是輕量級的。下面來看看怎麼使用
複製程式碼
通過MethodHandle進行方法呼叫一般需要:
- 建立MethodType物件,指定方法的簽名(即方法引數以及方法返回值的型別)。
- 在MethodHandles.Lookup中查詢型別為MethodType的MethodHandle;
- 傳入方法引數並呼叫MethodHandle.invoke或者MethodHandle.invokeExact方法。
MethodType
通過該物件設定方法的返回值以及引數列表中的型別。
第一個引數是返回型別,後面的剩餘引數是方法的引數型別。
MethodType.methodType(Class<?>class,Class<?>class1);
複製程式碼
Lookup
通過findXX方法可以得到相應的MethodHandle。
複製程式碼
invoke
invokeExact:呼叫此方法與直接呼叫底層方法一樣,需要做到引數型別精確匹配;
invoke:引數型別鬆散匹配,通過asType自動適配;
複製程式碼
示例程式碼:
public class MethodHandleTest {
public String toString(String s){
return "Hello"+s+"MethodHandle";
}
public static void main(String[] args) {
MethodHandleTest mht = new MethodHandleTest();
MethodHandle mh = getString();
try {
String o = (String) mh.invokeExact(mht, "ssss");
System.out.println(o);
}catch (Throwable throwable) {
throwable.printStackTrace();
}
MethodHandle methodHandle = mh.bindTo(mht);
try {
String ssss = (String) methodHandle.invokeWithArguments("ssss");
System.out.println(ssss);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
public static MethodHandle getString(){
MethodType mt = MethodType.methodType(String.class,String.class);
MethodHandle mh = null;
try {
mh = MethodHandles.lookup().findVirtual(MethodHandleTest.class,"toString",mt);
} catch (Exception e) {
e.printStackTrace();
}
return mh;
}
}
複製程式碼