MethodHandle类的实质是将某个具体的方法映射到MethodHandle上,通过MethodHandle直接调用该句柄所引用的底层方法,实际就是对可执行方法的引用。接着我们对MethodHandle类中的方法进行详细解析。
asCollector(Class
MethodHandles.Lookup publicLookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(String.class, int[].class);
MethodHandle deepToString = publicLookup.findStatic(AsCollector.class, "deepToString", mt);
MethodHandle ts1 = deepToString.asCollector(int[].class, 3);
System.out.println(ts1);
asFixedArity()方法,返回固定参数数量的方法句柄。
asVarargsCollector(Class
public static String deepToString(int a[]) {
return (a[0]) + "";}
public static String deepToString(int a) {
return a + "";}
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup publicLookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(String.class, int[].class);
MethodHandle deepToString = publicLookup.findStatic(AsFixedArity.class, "deepToString", mt);
MethodHandle varargs = deepToString.asVarargsCollector(int[].class);
MethodHandle fixed = deepToString.asFixedArity();
System.out.println(varargs);
System.out.println(fixed);
//System.out.println(deepToString.invoke(1));报错
System.out.println(varargs.invoke(1));//正常执行
//System.out.println(fixed.invoke(1));报错 参数数量是固定的
System.out.println(varargs.invoke(new int[]{1,2,3}));
System.out.println(fixed.invoke(new int[]{1,2,3}));}
按照参数的入参顺序,选择性的变换部分参数。
示例代码:
MethodHandles.Lookup publicLookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(boolean.class, Object.class);
MethodHandle equals = publicLookup.findVirtual(String.class, "equals", mt);
MethodHandle eq2 = equals.asSpreader(String[].class, 0);
//去掉一个参数,参数按入参顺序排列,Object类在第一,所以Object类被移除
MethodHandle eq3 = equals.asSpreader(String[].class, 1);
//去掉两个参数,参数按入参顺序排列,Object类在第一,String类在第二,所以Object、String类被移除
MethodHandle eq4 = equals.asSpreader(String[].class, 2);
System.out.println(equals);
System.out.println(eq2);
System.out.println(eq3);
System.out.println(eq4);
asType方法的作用是把当前方法句柄适配到新的MethodType上面,并产生一个新的方法句柄,但是asType方法在方法句柄的切换上存在限制,并不是所有的切换都可以实现。
示例代码:
MethodHandles.Lookup publicLookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(String.class, int.class);
MethodType mt1 = MethodType.methodType(String.class, Integer.class);
MethodHandle deepToString = publicLookup.findStatic(AsType.class, "deepToString", mt);
System.out.println(deepToString);
MethodHandle deepToString1 = deepToString.asType(mt1);
System.out.println(deepToString1);
将函数与对象捆绑在一起,把函数转变成了方法。
示例代码:
MethodHandles.Lookup publicLookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(String.class, int.class);
MethodHandle deepToString = publicLookup.findStatic(AsType.class, "deepToString", mt);
int a = 2;
//绑定参数a
MethodHandle deepToString1 = deepToString.bindTo(a);
//不能再接收其他参数
System.out.println(deepToString1.invoke());
System.out.println(deepToString1);
####6. invoke、invokeExact、invokeWithArguments方法
invoke():参数类型松散匹配,通过asType自动适配。
invokeExact():调用此方法与调用底层方法一样,但必须做到参数严格匹配。
invokeWithArguments(Object… arguments):先通过genericMethodType方法得到MethodType,再通过MethodHandle的asType转换得到新的MethodHandle,最后通过新MethodHandle的invokeExact方法完成调用。
示例代码:
MethodHandles.Lookup publicLookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(String.class, int.class);
MethodHandle deepToString = publicLookup.findStatic(AsType.class, "deepToString", mt);
System.out.println(deepToString.invoke(1));
System.out.println((String)deepToString.invokeExact(1));
System.out.println(deepToString.invokeWithArguments(1));