MethodHandle详解

MethodHandle类的实质是将某个具体的方法映射到MethodHandle上,通过MethodHandle直接调用该句柄所引用的底层方法,实际就是对可执行方法的引用。接着我们对MethodHandle类中的方法进行详细解析。

1. asCollector方法

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

2. asFixedArity和asVarargsCollector方法

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}));}

3. asSpreader方法

按照参数的入参顺序,选择性的变换部分参数。

示例代码:

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

4. asType方法

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

5. bindTo方法

将函数与对象捆绑在一起,把函数转变成了方法。

示例代码:

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

你可能感兴趣的:(Java7新特性)