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