二话不说,上代码
/**
*
* @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, , );
Object result2 = (String) mh.invokeExact(str, , );
// 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核心技术与最佳实践》

MethodHandle(方法句柄)系列之二:方法句柄的简单使用的更多相关文章

  1. SequoiaDB 系列之二 :SequoiaDB的简单CRUD操作

    上一篇通过一系列的操作,终于把SequoiaDB的集群部署到单台机器上了. 建议去安装体验一下吧. 在整个环境的部署的体验来看,并没有MongoDB的部署简单,但是比MongoDB的部署要清晰.Mon ...

  2. 初识Redis系列之二:安装及简单使用

    仅介绍windows下的安装 一:下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统平台的 ...

  3. Java 设计模式系列(二)简单工厂模式和工厂方法模式

    Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...

  4. .Net中的AOP系列之《方法执行前后——边界切面》

    返回<.Net中的AOP>系列学习总目录 本篇目录 边界切面 PostSharp方法边界 方法边界 VS 方法拦截 ASP.NET HttpModule边界 真实案例--检查是否为移动端用 ...

  5. Dagger2系列之使用方法

    本系列只讲使用方法和使用中遇到的问题,如果还对dagger2还不了解的童鞋儿可以参考文章: http://www.jianshu.com/p/cd2c1c9f68d4 http://www.jians ...

  6. 电容值E系列标称方法

    本节首先介绍常用的E系列标称方法,然后介绍电阻.电容器.电感器.二极管的分类.性能和识别方法,以及简单的实用电路. 一.E系列标称方法 厂家生产的电阻器,并不是包含任何阻值,就像人民币,只有1.2.5 ...

  7. MVC学习系列4--@helper辅助方法和用户自定义HTML方法

    在HTML Helper,帮助类的帮助下,我们可以动态的创建HTML控件.HTML帮助类是在视图中,用来呈现HTML内容的.HTML帮助类是一个方法,它返回的是string类型的值. HTML帮助类, ...

  8. Java学习-026-类名或方法名应用之二 -- 统计分析基础

    前文讲述了类名或方法的应用之一调试源码,具体请参阅:Java学习-025-类名或方法名应用之一 -- 调试源码 此文主要讲述类名或方法应用之二统计分析,通过在各个方法中插桩(调用桩方法),获取方法的调 ...

  9. 在keil 4中添加stc系列芯片的方法--【sky原创】

    在keil 4中添加stc系列芯片的方法: 1.从官网下载uv3.cdb的文件网址是:http://www.stcmcu.com/ 2.下载好后把uv3.cdb文件改成STC.cdb:3. 然后将[S ...

随机推荐

  1. struts2初始化探索(一)

    上篇文章已经介绍了struts2的简单使用,现在开始源码的学习. 本篇主要介绍struts2的初始化.对应的源码为StrutsPrepareAndExecuteFilter中的init方法. 先贴源码 ...

  2. python语法学习第六天--集合

    集合(set)是一个无序的不重复元素序列. 可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典. 创建格 ...

  3. 一文讲透Cluster API的前世、今生与未来

    作者:Luke Addison 原文链接:https://blog.jetstack.io/blog/cluster-api-past-present-and-future/ Cluster API是 ...

  4. HttpServletRequest与HttpServletResponse

    一. 简介:每当客户端给Web服务器发送一个http请求,web服务器就会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和respons ...

  5. 详解vue生命周期及每个阶段适合进行的操作

    VUE生命周期的四个阶段 create 创建 -------- 创建vue实例并初始化 mount 挂载 -------- 把vue实例和视图进行关联 update 更新 ------- 监听数据与视 ...

  6. Puppeteer笔记(一):Puppeteer简介

    一.Puppeteer简介 Puppeteer是NPM库,它提供了NodeJS高级API来控制Chrome.Puppeteer 默认以无头(无界面)方式运行,但也可以配置为运行有界面的Chrome. ...

  7. 让SpringBoot自动化配置不再神秘

    本文若有任何纰漏.错误,还请不吝指出! 注:本文提到的Spring容器或者Bean容器,或者Spring Bean容器,都是指同一个事情,那就是代指BeanFactory.关于BeanFactory, ...

  8. 浅析String、StringBuilder、StringBuffer

    谈谈我对 String.StringBuilder.StringBuffer 的理解 StringBuilder.StringBuffer 和 String 一样,都是用于存储字符串的. 1.那既然有 ...

  9. Poj2109 (2) k^n = p.

    二分法,由p最大值最小值的中间值开始猜k,通过比较pow(k,n)与p的大小来进一步精确k,直到找到. #include<stdio.h> #include<math.h> # ...

  10. python list 与 String 互相转换

    str0 = '127.0.0.1' list0 = str0.split('.') print(list0) #['127', '0', '0', '1'] str1 = '#'.join(list ...