MethodHandle(方法句柄)系列之二:方法句柄的簡單使用


 二話不說,上代碼
/**
 * 
 * @author LiuYeFeng<897908343@qq.com>
 * @date 2015年4月8日 下午10:41:13
 * @CopyRight 2015 TopView Inc
 * @version V1.0
 */
public class MethodHandleTest {
 
    public MethodHandle getHandler() {
        MethodHandle mh = null;
        MethodType mt = MethodType.methodType(String.class, int.class, int.class);
        MethodHandles.Lookup lk = MethodHandles.lookup();
         
        try {
            mh = lk.findVirtual(String.class, "substring", mt);
        } catch (Throwable e) {
            e.printStackTrace();
        }
         
        return mh;
    }
     
    public static void main(String[] args) throws Throwable {
        MethodHandle mh = new MethodHandleTest().getHandler();
        String str = "hello world";
         
        Object result1 = mh.invoke(str, 1, 3);
        Object result2 = (String) mh.invokeExact(str, 1, 3);
//      Object result2 = mh.invokeExact(str, new Integer(1), 3); 
        /**
         * 上面這句方法執行時報錯,因為方法類型為String.class, int.class, int.class
         * 而返回的類型為Object,與聲明中為String不符合
         * 其中第二個參數類型為Integer,與聲明中為int不符合,則類型適配不符合,系統報錯。
         */
         
        System.out.println("result 1:" + result1);
        System.out.println("result 1:" + result2);
    }
}
  代碼輸出結果均為el。
    接下來說一下方法句柄的調用過程,首先,在獲取方法句柄之前,先通過MethodType的靜態工廠方法,先生成一個包含方法參數類型、方法返回類型的的方法類型,也就是 MethodType mt = MethodType.methodType(String. class int . class int . class )。
    其次,獲取方法句柄要用到Lookup對象,比如代碼中的MethodHandles.Lookup lk,這個對象可以提供其所在環境中任何可見方法的方法句柄。我們可以將其比喻成包含有某個類對象的方法成員、方法的容器,通過lk.findVirtual(String.class"substring", mt);具體鎖定String類型中的某個方法,作為方法句柄返回。要從lookup對象中得到方法句柄,需要給出持有所需方法的類,方法的名稱,以及跟方法相匹配的方法類型。
    最后,獲取到方法句柄后,我們就可以通過方法句柄來調用底層的方法,這點上,跟反射中的方法調用類似。方法句柄提供兩個方法調用底層方法,invoke和invokeExact方法。invokeExact方法與直接調用底層方法是一樣的,比如代碼中,mh.invoke(str, 1, 2)就相當於直接調用str.substring(1, 3);具體兩個方法的區別下面再說。這里先解析一下這兩個方法的調用,方法的調用參數基本都一樣,第一個參數為方法的接受對象,即是哪個對象執行這個方法,接下來的參數就是執行方法所需要的參數。當然第一個參數,也就是方法的接受對象,可以通過方法句柄的bindto動態的參數綁定方法來綁定,從而使方法句柄的調用和普通方法調用沒區別,動態的參數綁定我們以后再研究。
    這里需要強調一下,靜態方法和動態方法之間的差別,靜態方法是不需要制定方法的接受對象的,而一般方法是需要的。
 
 
參考資料:《java程序員修煉之道》、《深入理解java7核心技術與最佳實踐》


免責聲明!

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



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