先把代码贴上来,用的是一样的代码
/**
*
* @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. 记录一下关于在工具类中更新UI使用RunOnUiThread犯的极其愚蠢的错误

    由于Android中不能在子线程中更新ui,所以平时在子线程中需要更新ui时可以使用Android提供的RunOnUiThread接口,但是最近在写联网工具类的时候,有时候会出现联网异常,这个时候为了 ...

  2. 自动化测试工具-Selenium IDE 教程一

    引言:这里介绍的是谷歌浏览种的插件,安装教程这里不再描述,网上有很多, 使用教程不是特别多,所以特地花时间整理此篇内容: 一:打开插件,欢迎界面 启动IDE后,将显示一个欢迎对话框. 如果这是您第一次 ...

  3. [hdu5353]模拟

    题意:有n个小朋友,每个小朋友手上有一些糖,考虑每两个相邻的小朋友a.b,可以选择执行3种操作中的任一种:(1)a给b一粒糖(2)b给a一粒糖(3)不进行任何动作,问能否通过确定每两个相邻的小朋友的操 ...

  4. php对接金蝶系统

    金蝶系统是强大的财务系统,可对公司的财务进行整理,所以有的时候需要去我php系统来对接金蝶系统,为金蝶系统生成各种单据.下面是php对接金蝶的流程. 各种方法已经封装好,直接可以调用就行了. 1.如果 ...

  5. 2018-06-18 Javascript 基础1

    js是一门基于对象的若类型语言,他和JAVA没有关系: js标签放置位置:1.内联 2.外部 3.内部: js代码是有执行顺序的,这点和css代码有所区别:当对象没有加载完或者还没加载的情况下js代码 ...

  6. .Net Core3.0 WebApi 项目框架搭建:目录

    一.目录 .Net Core3.0 WebApi 项目框架搭建 一:实现简单的Resful Api .Net Core3.0 WebApi 项目框架搭建 二:API 文档神器 Swagger .Net ...

  7. 「雕爷学编程」Arduino动手做(19)—震动报警模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  8. Angular核心概念之五---过滤器

    Filter:过滤器,用于在view中呈现数据时显示为另一种格式:过滤器的本质是一个函数,接收原始数据转换为新的格式进行输出: function(oldVal){ ... return newVal ...

  9. ORA-12519,TNS:no appropriate service handler found的问题 超过连接数

    http://www.2cto.com/database/201205/133542.html ORA-12519,TNS:no appropriate service handler found的问 ...

  10. unity---string.Format()

    string.Format用法 string.Format("{0}{1}{2}",str1,str2,str3) string.Format("{0:D2}{1:D2} ...