博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java.lang.invoke.Methodhandle
阅读量:7083 次
发布时间:2019-06-28

本文共 2343 字,大约阅读时间需要 7 分钟。

  hot3.png

简介

java7在JSR 292中增加了对动态类型语言的支持,使Java也可以像C语言那样将方法作为参数传递,其实现在lava.lang.invoke包中。MethodHandle作用类似于反射中的Method类,但它比Method类要更加灵活和轻量级。通过MethodHandle进行方法调用一般需要以下几步:

  1. 创建MethodType对象,指定方法的签名;
  2. 在MethodHandles.Lookup中查找类型为MethodType的MethodHandle;
  3. 传入方法参数并调用MethodHandle.invoke或者MethodHandle.invokeExact方法。

MethodType

可以通过MethodHandle类的type方法查看其类型,返回值是MethodType类的对象。也可以在得到MethodType对象之后,调用MethodHandle.asType(mt)方法适配得到MethodHandle对象。可以通过调用MethodType的静态方法创建MethodType实例,有三种创建方式:

  1. methodType及其重载方法:需要指定返回值类型以及0到多个参数;
  2. genericMethodType:需要指定参数的个数,类型都为Object;
  3. fromMethodDescriptorString:通过方法描述来创建。 创建好MethodType对象后,还可以对其进行修改,MethodType类中提供了一系列的修改方法,比如:changeParameterType、changeReturnType等。

Lookup

MethodHandle.Lookup相当于MethodHandle工厂类,通过findxxx方法可以得到相应的MethodHandle,还可以配合反射API创建MethodHandle,对应的方法有unreflect、unreflectSpecial等。

invoke

在得到MethodHandle后就可以进行方法调用了,有三种调用形式:

  1. invokeExact:调用此方法与直接调用底层方法一样,需要做到参数类型精确匹配;
  2. invoke:参数类型松散匹配,通过asType自动适配;
  3. invokeWithArguments:直接通过方法参数来调用。其实现是先通过genericMethodType方法得到MethodType,再通过MethodHandle的asType转换后得到一个新的MethodHandle,最后通过新MethodHandle的invokeExact方法来完成调用。
import java.lang.invoke.MethodHandle;import java.lang.invoke.MethodHandles;import java.lang.invoke.MethodHandles.Lookup;import java.lang.invoke.MethodType;public class MyMethodHandle {	@Override	public String toString() {		return super.toString() + "==MethodHandle";	}	public static void main(String[] args) throws Throwable{		MyMethodHandle handle = new MyMethodHandle();		MethodType methodType = MethodType.methodType(String.class);				Lookup lookup = MethodHandles.lookup();				MethodHandle methodHandle = lookup.findVirtual(MyMethodHandle.class, "toString", methodType);		String toString = (String) methodHandle.invokeExact(handle);		System.out.println(toString);				MethodHandle methodHandle2 = methodHandle.bindTo(handle);		String toString2 = (String) methodHandle2.invokeWithArguments();		System.out.println(toString2);				// 得到当前Class的不同表示方法,最后一个最好。一般我们在静态上下文用SLF4J得到logger用。          System.out.println(MethodHandle.class);          System.out.println(handle.getClass());          System.out.println(MethodHandles.lookup().lookupClass()); // like getClass()  	}	}

输出

MyMethodHandle@4dc63996==MethodHandleMyMethodHandle@4dc63996==MethodHandleclass java.lang.invoke.MethodHandleclass MyMethodHandleclass MyMethodHandle

转载于:https://my.oschina.net/zvc/blog/824786

你可能感兴趣的文章
Java集合整理
查看>>
postgresql导出表insert方式数据
查看>>
设计模式之门面模式
查看>>
node http核心模块
查看>>
[SCOI2010]序列操作 BZOJ1858 线段树
查看>>
Entity Framework在SaveChanges()之前拿到对象的自增长ID
查看>>
python读写csv文件
查看>>
数据溢出
查看>>
ECharts 在同一个页面添加多个图表 并 给图表绑定事件
查看>>
android studio 汉化 个性化 美化 快速操作项目 目录
查看>>
ionic2 textarea Automatically grows
查看>>
Azure和Bing Maps API示“.NET技术”例经验分享
查看>>
卡巴斯基联手功夫巨星成龙 五月鸟巢开唱
查看>>
android拨号器...
查看>>
Android手机拨打电话的开发实例
查看>>
个人关于面试的一些总结
查看>>
阿里云短信服务接口触发天级流控Permits:10
查看>>
2、hibernate的 save 保存失败的解决方法
查看>>
linux -- Ubuntu 命令技巧合集
查看>>
ANT无线通信技术(1) 简介
查看>>