zoukankan      html  css  js  c++  java
  • 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.classint.classint.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核心技术与最佳实践》
  • 相关阅读:
    屏蔽和开启”关机“功能
    资源管理器的自动完成功能
    js DOM(二)获取元素的方式、innerText、textContent、innerHTML、自定义属性
    js DOM(一)注册事件、修改标签属性和样式
    js ECMAscript(二)作用域,预解析,创建对象,内置对象
    旧create-react-app项目集成jest+enzyme
    create-react-app项目集成jest+enzyme测试react组件
    现代化前端测试
    puppeteer入门
    windows安装解压版redis
  • 原文地址:https://www.cnblogs.com/night-wind/p/4405532.html
Copyright © 2011-2022 走看看