package com.ljkj.test.person;
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
//在運(yùn)行時使用LambdaMetafactory為該非靜態(tài)方法getName()創(chuàng)建一個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)
* 六個參數(shù):
* 1. MethodHandles.Lookup caller:代表查找上下文(當(dāng)前類)與調(diào)用者的訪問權(quán)
* 2.String invokedName:要實(shí)現(xiàn)的方法的名字
* 3.MethodType invokedType : 調(diào)用點(diǎn)期望的方法參數(shù)的類型和返回值的類型(方法signature).
* 4.MethodType samMethodType : 函數(shù)對象將要實(shí)現(xiàn)的接口方法類型(泛型信息被擦除)
* 5.MethodHandle implMethod : 一個直接方法句柄(DirectMethodHandle), 描述在調(diào)用時將被執(zhí)行的具體實(shí)現(xiàn)方法
* (包含適當(dāng)?shù)膮?shù)適配, 返回類型適配, 和在調(diào)用參數(shù)前附加上捕獲的參數(shù)),
* 6. MethodType instantiatedMethodType : 函數(shù)接口方法替換泛型為具體類型后的方法類型, 通常和 samMethodType 一樣, 不同的情況為泛型:
* 比如函數(shù)接口方法定義為 void accept(T t) T為泛型標(biāo)識, 這個時候方法類型為(Object)Void, 在編譯時T已確定, 即T由String替換,
* 這時samMethodType就是 (Object)Void, 而instantiatedMethodType為(String)Void.
* 第4, 5, 6 三個參數(shù)來自class文件中的. 如上面引導(dǎo)方法字節(jié)碼中Method arguments后面的三個參數(shù)就是將應(yīng)用于4, 5, 6的參數(shù)
*/
final CallSite site = LambdaMetafactory.metafactory(lookup,
"invoke",
MethodType.methodType(GetterFunction.class), // 返回的函數(shù)對象
methodType, //函數(shù)對象將要實(shí)現(xiàn)的接口方法類型
lookup.findVirtual(Person.class, "getName", MethodType.methodType(Person.class)), // 具體執(zhí)行方法
methodType); // 函數(shù)對象將要實(shí)現(xiàn)的接口方法類型
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.調(diào)用這個對象的
MethodType.methodType(String.class,Person.class), // 3.方法的參數(shù)類型
virtual, // 5.最終的目標(biāo)方法方法
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);
}
}