美文网首页
在运行时使用LambdaMetafactory为该非静态方法ge

在运行时使用LambdaMetafactory为该非静态方法ge

作者: 盗生一 | 来源:发表于2021-04-04 12:51 被阅读0次
package com.ljkj.test.person;

public class Person {

    private String name;
    public Person(String name) {
        this.name = name;
    }
//在运行时使用LambdaMetafactory为该非静态方法getName()创建一个lambda
    public Person getName() {
        System.out.println("name = " + name);
        return new Person("2");
    }

}
package com.ljkj.test.person;

import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.function.Function;

public class MyMainSuccess {

    public static void main(String[] args) throws Throwable {
        GetterFunction getterFunction;

        final MethodHandles.Lookup lookup = MethodHandles.lookup();

        MethodType methodType = MethodType.methodType(Person.class, Person.class);
        /**
         * LambdaMetafactory.metafactory(Lookup, String, MethodType, MethodType, MethodHandle, MethodType)
         * 六个参数:
         * 1. MethodHandles.Lookup caller:代表查找上下文(当前类)与调用者的访问权
         * 2.String invokedName:要实现的方法的名字
         * 3.MethodType invokedType : 调用点期望的方法参数的类型和返回值的类型(方法signature).
         * 4.MethodType samMethodType :  函数对象将要实现的接口方法类型(泛型信息被擦除)
         * 5.MethodHandle implMethod : 一个直接方法句柄(DirectMethodHandle), 描述在调用时将被执行的具体实现方法
         * (包含适当的参数适配, 返回类型适配, 和在调用参数前附加上捕获的参数),
         * 6. MethodType instantiatedMethodType : 函数接口方法替换泛型为具体类型后的方法类型, 通常和 samMethodType 一样, 不同的情况为泛型:
         *         比如函数接口方法定义为 void accept(T t)  T为泛型标识, 这个时候方法类型为(Object)Void,  在编译时T已确定, 即T由String替换,
         *         这时samMethodType就是 (Object)Void, 而instantiatedMethodType为(String)Void.
         *                 第4, 5, 6 三个参数来自class文件中的. 如上面引导方法字节码中Method arguments后面的三个参数就是将应用于4, 5, 6的参数
         */
        final CallSite site = LambdaMetafactory.metafactory(lookup,
                "invoke",
                MethodType.methodType(GetterFunction.class), // 返回的函数对象
                methodType, //函数对象将要实现的接口方法类型
                lookup.findVirtual(Person.class, "getName", MethodType.methodType(Person.class)), // 具体执行方法
                methodType); // 函数对象将要实现的接口方法类型
        getterFunction = (GetterFunction) site.getTarget().invokeExact();
        Person a11nn = (Person) getterFunction.invoke(new Person("A11nn"));
        a11nn.getName();
//        System.out.println(getterFunction.invoke(new Person("Ann")));
    }

    @FunctionalInterface
    interface GetterFunction {
        Person invoke(final Person callable);
    }

}
package com.ljkj.test.person;

import java.lang.invoke.*;

public class MyMain {

    public static void main(String[] args) throws Throwable {
        GetterFunction getterFunction;


        MethodHandle virtual =
                MethodHandles.lookup().findVirtual(Person.class, "getName", MethodType.methodType(String.class));


        CallSite site = LambdaMetafactory.metafactory(
                MethodHandles.lookup(),
                "getName", // 2.这个方法
                MethodType.methodType(GetterFunction.class), // 1.调用这个对象的
                MethodType.methodType(String.class,Person.class), // 3.方法的参数类型
                virtual, // 5.最终的目标方法方法
                MethodType.methodType(String.class,Person.class)); // 4.和3几乎相同
        getterFunction = (GetterFunction) site.getTarget().invokeExact();
        System.out.println(getterFunction.getName(new Person("Ann11")));
    }


    @FunctionalInterface
    private interface GetterFunction {

        String getName(Person person);

    }

}

相关文章

网友评论

      本文标题:在运行时使用LambdaMetafactory为该非静态方法ge

      本文链接:https://www.haomeiwen.com/subject/fnclkltx.html