Java7新特性——MethodHandle

Java7为间接调用方法引入了新的API。其中的关键是java.lang.invoke包,即方法句柄。你可以把它看做反射的现代化方式,但它不像反射API那样有时会显得冗长、繁重和粗糙。方法句柄是将invokedynamic引入JVM项目中的一部分。

一、MethodHandle

什么是Method Handle?它是对可直接执行的方法(或域、构造方法等)的类型化引用。还有一种说法是,方法句柄是一个有能力安全调用方法的对象。

主要API

MethodType type():Reports the type of this method handle.

Object invoke(Object... args):Invokes the method handle, allowing any caller type descriptor,
and optionally performing conversions on arguments and return values.

Object invokeExact(Object... args):Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.

Object invokeWithArguments(Object... arguments):Performs a variable arity invocation, passing the arguments in the given list to the method handle, as if via an inexact invoke from a call site which mentions only the type Object, and whose arity is the length of the argument list.

Object invokeWithArguments(java.util.List<?> arguments):Performs a variable arity invocation, passing the arguments in the given array to the method handle, as if via an inexact invoke from a call site which mentions only the type Object, and whose arity is the length of the argument array.

MethodHandle bindTo(Object x):Binds a value x to the first argument of a method handle, without invoking it.

二、MethodType

MethodTYpe是表示方法签名类型的不可变对象。每个方法句柄都有一个MethodType实例,用来指明方法的返回类型和参数类型。但它没有方法的名字和“接收者类型”,即调用的实例方法的类型。

主要API(static):Finds or creates a method type with the given components.

  • MethodType methodType(Class<?> rtype, Class<?>[] ptypes)
  • MethodType methodType(Class<?> rtype, List<Class<?>> ptypes)
  • MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes)
  • MethodType methodType(Class<?> rtype)
  • MethodType methodType(Class<?> rtype, Class<?> ptype0)
  • MethodType methodType(Class<?> rtype, MethodType ptypes)

三、查找方法句柄

要从lookup对象中得到方法句柄,你需要给出持有所需方法的类、方法的名称,以及跟你所需的方法签名相匹配的MethodType。

1、获取Lookup对象

MethodHandles.Lookup lookup = MethodHandles.lookup();

2、使用findXxx方法

lookup.findXxx方法提供了各种查找方式

MethodHandle findVirtual(Class<?> refc, String name, MethodType type):Produces a method handle for a virtual method.
The type of the method handle will be that of the method, with the receiver type refc prepended.
The method and all its argument types must be accessible to the lookup object.

3、调用句柄

Object rValue = methodHandle.invokeXxx(...)。

四、官方案例

Object x, y; String s; int i;
MethodType mt; MethodHandle mh;
MethodHandles.Lookup lookup = MethodHandles.lookup();
// mt is (char,char)String
mt = MethodType.methodType(String.class, char.class, char.class);
mh = lookup.findVirtual(String.class, "replace", mt);
s = (String) mh.invokeExact("daddy",'d','n');
// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
assertEquals(s, "nanny");
// weakly typed invocation (using MHs.invoke)
s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
assertEquals(s, "savvy");
// mt is (Object[])List
mt = MethodType.methodType(java.util.List.class, Object[].class);
mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
assert(mh.isVarargsCollector());
x = mh.invoke("one", "two");
// invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
assertEquals(x, java.util.Arrays.asList("one","two"));
// mt is (Object,Object,Object)Object
mt = MethodType.genericMethodType(3);
mh = mh.asType(mt);
x = mh.invokeExact((Object)1, (Object)2, (Object)3);
// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
assertEquals(x, java.util.Arrays.asList(1,2,3));
// mt is ()int
mt = MethodType.methodType(int.class);
mh = lookup.findVirtual(java.util.List.class, "size", mt);
i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
// invokeExact(Ljava/util/List;)I
assert(i == 3);
mt = MethodType.methodType(void.class, String.class);
mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
mh.invokeExact(System.out, "Hello, world.");
// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V

五、测试

六、Java的方法间接访问技术比较

Java的方法间接访问技术比较

七、其它 

  • Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值