先把代码贴上来,用的是一样的代码
/**
*
* @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. React Native超简单完整示例-tabs、页面导航、热更新、用户行为分析

    初学React Native,如果没有人指引,会发现好多东西无从下手,但当有人指引后,会发现其实很简单.这也是本人写这篇博客的主要原因,希望能帮到初学者. 本文不会介绍如何搭建开发环境,如果你还没有搭 ...

  2. Android 电池管理系统架构总结 Android power and battery management architecture summaries

    文章目录 1 整体架构 2 设计构架 2.1 driver 2.1.1 Charger.ko 2.1.2 Battery.ko 2.2 power supply 2.2.1 基础架构 2.2.2 代码 ...

  3. CSS理论:margin-left在float中的运用

    源码如下: margin-left 指的是左边的外边距,为正数时,左边间距增大,div向右偏移,为负数时,左边间距减少,相反往左偏移 双飞翼 .wrap { width: 100%; margin: ...

  4. spring源码解析之前置知识点

    本文是作者原创,版权归作者所有.若要转载,请注明出处. 最近在看spring源码,但是spring的体系太庞大了,在这里记录一下阅读源码中遇到知识点 @PostConstruct 被注解的方法,在对象 ...

  5. Asp.net Core 3.1 Razor视图模版动态渲染PDF

    Asp.net Core 3.1 Razor视图模版动态渲染PDF 前言 最近的线上项目受理回执接入了电子签章,老项目一直是html打印,但是接入的电子签章是仅仅对PDF电子签章,目前还没有Html电 ...

  6. node的fs模块

    node的file system模块提供的api有同步和异步两种模式(大多数情况下都是用的异步方法,毕竟异步是node的特色,至于提供同步方法,可能应用程序复杂的时候有些场景使用同步会比较合适).异步 ...

  7. JS 如何获取自定义属性

    <script>var testEle = document.getElementById("test"); testEle.setAttribute("de ...

  8. Java集合--阻塞队列及各种实现的解析

    阻塞队列(Blocking Queue) 一.队列的定义 说的阻塞队列,就先了解下什么是队列,队列也是一种特殊的线性表结构,在线性表的基础上加了一条限制:那就是一端入队列,一端出队列,且需要遵循FIF ...

  9. poj3683 2-SAT 同上一道

    Priest John's Busiest Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10151   Accep ...

  10. 关闭 WordPress 自动更新

    # 方法一 推荐!编辑 WordPress 网站目录下的 wp-config.php 文件,添加如下代码: define( 'AUTOMATIC_UPDATER_DISABLED', true ); ...