一.总述

  java7为间接调用方法提供了MethodHandle类,即方法句柄。可以将其看作是反射的另一种方式。

这是使用MethodHandle调用方法的一个例子:

public class Test {
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(String.class,char.class,char.class);
try {
MethodHandle mh = lookup.findVirtual(String.class,"replace", mt);
String handled_str = (String) mh.invoke("abc",'a','c');
System.out.print(handled_str);
} catch (NoSuchMethodException | IllegalAccessException e) {
e.printStackTrace();
}
}
}

  用MethodHandle调用方法的流程为:

  • (1) 创建MethodType,获取指定方法的签名
  • (2) 在Lookup中查找MethodType的方法句柄MethodHandle
  • (3) 传入方法参数通过MethodHandle调用方法

二.MethodType

MethodType表示一个方法类型的对象,每个MethodHandle都有一个MethodType实例,MethodType用来指明方法的返回类型和参数类型。其有多个工厂方法的重载。

static MethodType	methodType(Class<?> rtype)

static MethodType	methodType(Class<?> rtype, Class<?> ptype0)

static MethodType	methodType(Class<?> rtype, Class<?>[] ptypes)

static MethodType	methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes)

static MethodType	methodType(Class<?> rtype, List<Class<?>> ptypes)

static MethodType	methodType(Class<?> rtype, MethodType ptypes)

如上面示例代码中的

MethodType mt = MethodType.methodType(String.class,char.class,char.class);就得到了一个方法的参数类型为char,char,返回类型为String的MethodType。

三.Lookup

  MethodHandle.Lookup可以通过相应的findxxx方法得到相应的MethodHandle,相当于MethodHandle的工厂方法。查找对象上的工厂方法对应于方法、构造函数和字段的所有主要用例。下面是官方API文档对findxxx的说明,这些工厂方法和结果方法处理的行为之间的对应关系:

可以看出findStatic相当于得到的是一个static方法的句柄,findVirtual找的是普通方法。其他的可以从官方文档中阅读得知,这里不详细说明了。

四. MethodHandle

  MethodHandle是什么?简单的说就是方法句柄,通过这个句柄可以调用相应的方法。官方文档对其的解释为:

“ A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values. These transformations are quite general, and include such patterns as conversion, insertion, deletion, and substitution.”

翻译如下:

方法句柄是对底层方法、构造函数、字段或类似低级操作的类型化、直接可执行的引用,具有参数或返回值的可选转换。这些转换非常普遍,包括转换、插入、删除和替换等模式

常用的方法为invokexxx,如下图

  其中需要注意的是invokeinvokeExact,前者在调用的时候可以进行返回值和参数的类型转换工作,而后者是精确匹配的。比如,在MethodType中指定的参数类型是int,如果你用invoke调用时指定的参数是Integer类型,方法调用是可以运行的,这是通过MethodHandle类的astype方法产生一个新的方法句柄。而如果用的是invokeExact则在运行时会报错。

  另外一个需要注意的是invokexxx的所有方法返回的是Object,调用时若有返回结果一般需进行强制类型转换。

  最后还有一点,如果调用的方法没有返回值,那么在MethodType的工厂方法中的返回值类型写为void.class

java的MethodHandle类详解的更多相关文章

  1. java之StringBuffer类详解

    StringBuffer 线程安全的可变字符序列. StringBuffer源码分析(JDK1.6): public final class StringBuffer extends Abstract ...

  2. java之AbstractStringBuilder类详解

    目录 AbstractStringBuilder类 字段 构造器 方法   public abstract String toString() 扩充容量 void  expandCapacity(in ...

  3. java之StringBuilder类详解

    StringBuilder 非线程安全的可变字符序列 .该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍).如果可能,建议优先采用该类,因为在 ...

  4. java.lang.Thread类详解

    java.lang.Thread类详解 一.前言 位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口,今天我们来学习一下Thread类,在学习Thread类之前 ...

  5. Java中dimension类详解

    Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788

  6. java之Matcher类详解

    在JDK 1.4中,Java增加了对正则表达式的支持. java与正则相关的工具主要在java.util.regex包中:此包中主要有两个类:Pattern.Matcher. Matcher  声明: ...

  7. java的ReentrantLock类详解

    ReentrantLock 能用于更精细化的加锁的Java类, 通过它能更清楚了解Java的锁机制 ReentrantLock 类的集成关系有点复杂, 既有内部类, 还有多重继承关系 类的定义 pub ...

  8. Java的String类详解

    Java的String类 String类是除了Java的基本类型之外用的最多的类, 甚至用的比基本类型还多. 同样jdk中对Java类也有很多的优化 类的定义 public final class S ...

  9. Java Properties工具类详解

    1.Java Properties工具类位于java.util.Properties,该工具类的使用极其简单方便.首先该类是继承自 Hashtable<Object,Object> 这就奠 ...

随机推荐

  1. 分布式理论系列(二)一致性算法:2PC 到 3PC 到 Paxos 到 Raft 到 Zab

    分布式理论系列(二)一致性算法:2PC 到 3PC 到 Paxos 到 Raft 到 Zab 本文介绍一致性算法: 2PC 到 3PC 到 Paxos 到 Raft 到 Zab 两类一致性算法(操作原 ...

  2. Smart Pointe

    http://blog.chinaunix.net/uid-625789-id-2720884.html

  3. Python打开文件open()的注意事项

    刚刚用open(fileName)来打开txt格式的文件,总是出现错误,总是找不到文件读取的内容,后来才发现是open()在使用过程中自动关闭了.这里介绍另种方法解决这个问题. 第一种方法. with ...

  4. unidac 访问sql server 字符查询参数失效问题及解决办法

    在帮朋友调试kbmmw 服务器的时候,发现用uindac 访问sql server作为后台时,碰见一个问题. 具体如下: cx.Close; cx.sql.add('select * from T w ...

  5. clone一行div tr 每次增量赋值

    $("#add_tan").click(function () { num++; $("tbody tr.tab_xue").eq(0).clone(true) ...

  6. 【转】WIFI基本知识整理

    WIFI基本知识整理 这里对wifi的802.11协议中比较常见的知识做一个基本的总结和整理,便于后续的学习.因为无线网络中涉及术语很多,并且许多协议都是用英文描述,所以有些地方翻译出来会有歧义,这种 ...

  7. CocoaPods:library not found for -lPods

    This is my first shot to write a blog in English. Enjoy! ;) CocoaPods is a popular way to control iO ...

  8. oracle ebs常规小看点

      1. 在oracle applications 11i 中如何快速获得上次查询的SQL 语句 方法:我们不必使用SQL Trace 来获得,有一个简单的办法,即:帮助->诊断->检查- ...

  9. Android-Sqlite3的使用

    Sqlite3的使用: adb remount --> 挂载上 adb devices -->查看设备 adb shell -->进入Android文件系统 cd /data/dat ...

  10. 在Excel中导入文本文件(CSV/TXT),自定义隔离符号

    经常需要在Excel中导入文本文件,但是需要自定义隔离符号,例如空格或者逗号,参考一下方法: