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> 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

五、测试

Java7新特性——MethodHandle_第1张图片

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

Java7新特性——MethodHandle_第2张图片 Java的方法间接访问技术比较

七、其它 

  • Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

你可能感兴趣的:(版本新特性,MethodHandle,方法句柄,JDK7新特性)