java的MethodHandle类详解
一.总述
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,如下图

其中需要注意的是invoke和invokeExact,前者在调用的时候可以进行返回值和参数的类型转换工作,而后者是精确匹配的。比如,在MethodType中指定的参数类型是int,如果你用invoke调用时指定的参数是Integer类型,方法调用是可以运行的,这是通过MethodHandle类的astype方法产生一个新的方法句柄。而如果用的是invokeExact则在运行时会报错。
另外一个需要注意的是invokexxx的所有方法返回的是Object,调用时若有返回结果一般需进行强制类型转换。
最后还有一点,如果调用的方法没有返回值,那么在MethodType的工厂方法中的返回值类型写为void.class
java的MethodHandle类详解的更多相关文章
- java之StringBuffer类详解
StringBuffer 线程安全的可变字符序列. StringBuffer源码分析(JDK1.6): public final class StringBuffer extends Abstract ...
- java之AbstractStringBuilder类详解
目录 AbstractStringBuilder类 字段 构造器 方法 public abstract String toString() 扩充容量 void expandCapacity(in ...
- java之StringBuilder类详解
StringBuilder 非线程安全的可变字符序列 .该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍).如果可能,建议优先采用该类,因为在 ...
- java.lang.Thread类详解
java.lang.Thread类详解 一.前言 位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口,今天我们来学习一下Thread类,在学习Thread类之前 ...
- Java中dimension类详解
Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788
- java之Matcher类详解
在JDK 1.4中,Java增加了对正则表达式的支持. java与正则相关的工具主要在java.util.regex包中:此包中主要有两个类:Pattern.Matcher. Matcher 声明: ...
- java的ReentrantLock类详解
ReentrantLock 能用于更精细化的加锁的Java类, 通过它能更清楚了解Java的锁机制 ReentrantLock 类的集成关系有点复杂, 既有内部类, 还有多重继承关系 类的定义 pub ...
- Java的String类详解
Java的String类 String类是除了Java的基本类型之外用的最多的类, 甚至用的比基本类型还多. 同样jdk中对Java类也有很多的优化 类的定义 public final class S ...
- Java Properties工具类详解
1.Java Properties工具类位于java.util.Properties,该工具类的使用极其简单方便.首先该类是继承自 Hashtable<Object,Object> 这就奠 ...
随机推荐
- [Training Video - 2] [Groovy Introduction]
Building test suites, Test cases and Test steps in SOAP UI Levels : test step level test case level ...
- centos7安装kubernetes 1.1
原文地址:http://foxhound.blog.51cto.com/1167932/1717105 前提:centos7 已经update yum update -y 一.创建yum源 maste ...
- csdn的博客上传word图片
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- 二)quartz.properties
The Properties File Quartz uses a properties file called (kudos on the originality) quartz.propertie ...
- 从Objective-C到Swift,你必须会的(四)DLog
调试的时候打断点太慢,所以输出log就是一个很好的选择了.断点,一行一行的按,太麻烦了.从log里一条一条的看,很快就可以找到到哪个函数的哪个地方这个代码就没执行了.这里不详细讨论调试技巧的事.不过大 ...
- Receiving Transaction Processor Conundrum
what would we do if we are faced with a situation to execute a receiving transaction in oracle ebusi ...
- Android-开关机的广播
在上一篇博客Android-sdcard广播的接收处理,中介绍了,如何订阅接收者,去接收系统发送的Sdcard状态改变广播,而这篇博客是订阅接收者,去接收开机/关机的广播 Android操作系统在开机 ...
- 在ASP.NET Core2上操作MongoDB就是能这么的简便酷爽(自动完成分库分表)
NoSQL是泛指非关系型的数据库,现今在我们的项目中也多有使用,其独特的优点为我们的项目架构带来了不少亮点,而我们这里的主角(MongoDB)则是NoSQL数据库家族中的一种.事实上,NoSQL数据库 ...
- github的使用经历
首先我打开百度搜索markdown,点击这个在线编辑器,开始编写,如下图: 预览效果如下: 然后打开github的网页登录后,点击下图这个标志: 然后给给要上传的一个命名: 然后选择README 确认 ...
- JQuery --- 第五期 (JQuery节点操作)
学习笔记 1.JQuery添加节点相关方法 <!DOCTYPE html> <html lang="en"> <head> <meta c ...