先把代码贴上来,用的是一样的代码
/**
*
* @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);
}
}

    invoke和invokeExact方法的区别,从名字上来看,明显是后者准确性更高,或者说要求更严格。invokeExact方法在调用时要求严格的类型匹配,方法的返回值类型也在考虑范围之内,如同上面代码中注释掉的一句。如果把Object result2 = (String) mh.invokeExact(str, 13);中的(String)去掉类型转换的话,在调用的时候该方法会认为返回值是Object类型而不是String类型,然后系统报错。

       与invokeExact方法不同,invoke方法允许更加松散的调用方式。它会尝试在调用的时候进行返回值和参数类型的转换工作。这是通过MethodHandle类的asType方法来完成的,asType方法的作用是把当前方法句柄适配到新的MethodType上面,并产生一个新的方法句柄。当方法句柄在调用时的类型与其声明的类型完全一致的时候,调用invoke方法等于调用invokeExact方法;否则,invoke方法会先调用asType方法来尝试适配到调用时的类型。如果适配成功,则可以继续调用。否则会抛出相关的异常。这种灵活的适配机制,使invoke方法成为在绝大多数情况下都应该使用的方法句柄调用方式。

进行类型匹配的基本规则是对比返回值类型和每个参数的类型是否都可以相互匹配。假设源类型为S,目标类型为T,则基本规则如下:

        1、可以通过java的类型转换来完成,一般从子类转成父类,比如从String到Object类型;
        2、可以通过基本类型的转换来完成,只能将类型范围的扩大,比如从int切换到long;
        3、可以通过基本类型的自动装箱和拆箱机制来完成,例如从int到Integer;
        4、如果S有返回值类型,而T的返回值类型为void,则S的返回值会被丢弃。
        5、如果S的返回值是void,而T的返回值是引用类型,T的返回值会是null;
        6、如果S的返回值是void,而T的返回值是基本类型,T的返回值会是0;
 
    第1、2、3条很好理解,第4、5、6条感觉原理都一样,我就用个新例子说明。
public class MethodHandleTest {

    public MethodHandle getHandler() {
MethodHandle mh = null;
MethodType mt = MethodType.methodType(void.class);
MethodHandles.Lookup lk = MethodHandles.lookup(); try {
mh = lk.findVirtual(MethodHandleTest.class, "print", mt);
} catch (Throwable e) {
e.printStackTrace();
} return mh;
} public void print() {
System.out.println("print");
} public static void main(String[] args) throws Throwable {
MethodHandleTest mht = new MethodHandleTest();
MethodHandle mh = mht.getHandler(); int result1 = (int) mh.invoke(mht);
Object result2 = mh.invoke(mht); System.out.println("result 1:" + result1);
System.out.println("result 2:" + result2);
}
}

程序输出结果是:

print
print
result 1:0
result 2:null
 
 
参考资料:《java程序员修炼之道》、《深入理解java7核心技术与最佳实践》

MethodHandle(方法句柄)系列之三:invoke和invokeExact的区别的更多相关文章

  1. java方法句柄-----2.方法句柄的获取、变换、特殊方法句柄

    目录 1.获取方法句柄 1.1查找构造方法.一般方法和静态方法的方法句柄 1.2 查找类中的特殊方法(类中的私有方法) 1.3 查找类中静态域和一般域 1.4 通过反射API得到的Constructo ...

  2. java方法句柄-----1.方法句柄类型、调用

    目录 方法句柄 1.方法句柄的类型 1.1MethodType类的对象实例的创建 1.1.1 通过指定参数和返回值的类型来创建MethodType.[显式地指定返回值和参数的类型] 1.1.2 通过静 ...

  3. MethodHandle(方法句柄)系列之二:方法句柄的简单使用

     二话不说,上代码 /** * * @author LiuYeFeng<897908343@qq.com> * @date 2015年4月8日 下午10:41:13 * @CopyRigh ...

  4. MethodHandle(方法句柄)系列之一:MethodHandle和MethodType

        阅读此文章的作者建议先了解java反射和动态代理.       java7中为间接调用方法引入了新的api,其中最关键的是java.lang.invoke包,即方法句柄.我们可以看成是java ...

  5. java方法句柄-----4.你所不知道的MethodHandle【翻译】

    Method Handles in Java 1.介绍 在本文中,我们将探讨一个重要的API,它是在Java 7中引入的,并在Java 7版本之后更加完善:全限定名是:Java.lang.invoke ...

  6. java方法句柄-----5.Method Handles in Java

    Method Handles in Java 目录 Method Handles in Java 1.介绍 2.什么是MethodHandle 3. Method Handles vs Reflect ...

  7. 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三

       手把手叫你玩转网络编程系列之三    完毕port(Completion Port)具体解释                                                    ...

  8. 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之三 —— 配置

    ==== 目录 ==== 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之一 —— 开篇 跟我学: 使用 fireasy 搭建 asp.net core 项目系列之二 —— ...

  9. java方法句柄-----3.方法句柄的实现接口

    目录 1.使用方法句柄实现接口 1.使用方法句柄实现接口   2.3节介绍的动态代理机制可以在运行时为多个接口动态创建实现类,并拦截通过接口进行的方法调用.方法句柄也具备动态实现一个接口的能力.这是通 ...

随机推荐

  1. Spring官网阅读(二)(依赖注入及方法注入)

    上篇文章我们学习了官网中的1.2,1.3两小节,主要是涉及了容器,以及Spring实例化对象的一些知识.这篇文章我们继续学习Spring官网,主要是针对1.4小节,主要涉及到Spring的依赖注入.虽 ...

  2. 【杂谈】Disruptor——RingBuffer问题整理(一)

    纯CAS为啥比加锁要快? 同样是修改数据,一个采用加锁的方式保证原子性,一个采用CAS的方式保证原子性. 都是能够达到目的的,但是常用的锁(例如显式的Lock和隐式的synchonized),都会把获 ...

  3. 【Hadoop离线基础总结】MapReduce增强(下)

    MapReduce增强(下) MapTask运行机制详解以及MapTask的并行度 MapTask运行流程 第一步:读取数据组件InputFormat(默认TextInputFormat)会通过get ...

  4. pyhanlp安装教程

    1.hanlp简介 HanLP是由一系列模型与算法组成的Java工具包,目标是普及自然语言处理在生产环境中的应用.HanLP具备功能完善.性能高效.架构清晰.语料时新.可自定义的特点. Hanlp具有 ...

  5. Airtable base

    PC端习惯了SQL Server Express.Access数据库的强大,安卓端再去用Microsoft Office.WPS,能让你怀疑人生.使用Airtable是个不错的方案,workspace ...

  6. vue-multi-module【多模块集成的vue项目,多项目共用一份配置,可以互相依赖,也可以独立打包部署】

    基于 vue-cli 2 实现,vue 多模块.vue多项目集成工程 Github项目地址 : https://github.com/BothEyes1993/vue-multi-module 目标: ...

  7. JVM 调优测试 之 故意分配小的堆空间,观察gc回收打印的内容

    测试代码如下: @Test public void testPrintGcDetail(){ HashMap<String, List> gcMap = new HashMap<&g ...

  8. 预测算法:基于UCF的电影推荐算法

    #基于用户的推荐类算法 from math import sqrt #计算两个person的欧几里德距离 def sim_distance(prefs,person1,person2): si = { ...

  9. RunLoop总结

    参考学习了YY大神的http://blog.ibireme.com/2015/05/18/runloop/#mode RunLoop: 看做是一个对象,这个对象管理了其需要处理的事件和消息,并提供了一 ...

  10. 程序员的踩坑经验总结(一):如何把Bug的偶现变必现

    程序员的踩过的坑也是可以分类的,很常见又很难解决的一类是偶然的现象,表现起来比较怪异. 而把一个问题Bug的偶现变成必现,是开发人员的一种能力.我认为也应该是测试人员的一种能力,但是各个公司要求不一样 ...