反射(Reflect)作為Java最重要的一種機制,相信大家一定都很熟悉了,今天要介紹另一種和反射機制類似的方法調用機制——MethodHandle。
MethodHandle是Java7引入的一種機制,主要是為了JVM支持動態語言。
一個MethodHandle調用示例
首先,讓指北君給大家演示一下最基本的MethodHandle使用。
第一步:創建查找對象:Lookup
// 獲取Look用于查找方法句柄
MethodHandles.Lookup lookup = MethodHandles.lookup();
第二步:創建方法類型:MethodType
構造方法的返回值類型,參數類型
// 方法類型,描述返回值和參數,第一個參數為返回值類型,void則為void.class。第二個參數開始為被調用方法的參數類型
MethodType mt = MethodType.methodType(boolean.class, String.class, int.class);
第三步:查找方法句柄
Lookup的findVirtual查找成員方法
//查找方法句柄,參數1:調用類,參數2:方法名,參數3:方法類型
MethodHandle handle = lookup.findVirtual(String.class, "startsWith", mt);
第四步:方法調用
通過MehodHandle的invoke方法執行,并返回結果
//方法調用,參數1:實例,參數2..n:方法參數
Boolean value = (Boolean)handle.invoke("the i am in the room", "the", 0);
以上就是一個簡單的調用示例。
核心代碼解讀
上面我們展示了一個最進本MethodHandle方式的方法調用,下面我們將對其中用到的主要類進行介紹。這些主要的類包含MethodType,MethodHandle,MethodHandles及Lookup。
MethodType
首先,我們來看看Methodtype,MethodType是用來封裝方法輸入輸出類型的,包含方法的返回和方法的參數。MethodType構造方法為私有,只能通過MethodType提供的靜態工具方法來獲取實例
/**
* 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中常用的工具方法有:
- 大于一個參數
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);
}
- 無參數
public static MethodType methodType(Class< ? > rtype) {
return makeImpl(rtype, NO_PTYPES, true);
}
工具方法都通過makeImple方法來封裝MethodType實例,指北君帶領大家來看看makeImple中做了哪些事情:
- 參數檢查
- 返回值的類型不能為null,如果無返回使用void.class
- 參數類型不能為null,且不能為void.class
- 使用緩存表緩存MethodType實例,優化處理
- 如果非信任模式(trusted==false),則克隆參數數組
這里需要注意MethodType重寫了hashCode方法,從邏輯看參數數組克隆不影響同類型的緩存機制。
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);
}
除了靜態工具方法外,MethodType還有幾個實例方法,主要為差異性較小的MethodType提供快速獲取實例的方法。包含:
- changeParameterType
- insertParameterTypes
- appendParameterTypes
- dropParameterTypes
MethodHandle
MethodHandle為抽象類,但是里面提供了大量的原生方法,提供底層訪問,也是方法調用的核心邏輯。這部分涉及MethodHandle的機制實現,對于使用功能來說指北君就不在此展開了。
@HotSpotIntrinsicCandidate
public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
@HotSpotIntrinsicCandidate
public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;
調用方法
MethodHandles, Lookup
MethodHandles不是MethodHandle的實現,他提供工具用于幫助獲取MethodHandle,我們主要使用到lookup(),publicLookup()
@CallerSensitive注解,可以使Reflection.getCallerClass()獲取到調用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構造方法主要傳入兩個參數:
- lookupClass搜尋的類,
- allowedModes:許可模式。
最后,通過Lookup的findXXX獲取到MethodHandle,詳細說明見下表:
查找方法
小結
關于MethodHandle的基本使用就基本講完,這里附上一張類圖便大家理解:
-
參數
+關注
關注
11文章
1867瀏覽量
32894 -
代碼
+關注
關注
30文章
4891瀏覽量
70331 -
Method
+關注
關注
0文章
9瀏覽量
7394 -
JVM
+關注
關注
0文章
160瀏覽量
12539
發布評論請先 登錄
gpio示例調用流程
求助,請問有沒有UM2262調用加密庫的具體示例?
淺談C、C++ 和 ARM 匯編語言之間的調用
python代碼示例之基于Python的日歷api調用代碼實例

API-Shop-OCR-營業執照識別API接口Python調用示例代碼說明

移動數據的編程示例

評論