java package edu.project5;
import java.lang.invoke.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import static java.lang.invoke.MethodType.methodType;
public class LambdaExample {
public static void main(String[] args) throws Throwable {
// Define a simple record class
record Person(String name, int age) {
}
// Create a LambdaMetafactory
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle methodHandle = lookup.findVirtual(Person.class, "name", methodType(String.class));
CallSite callSite = LambdaMetafactory.metafactory(
lookup,
"get",
MethodType.methodType(Supplier.class, Person.class),
MethodType.methodType(String.class, Person.class),
methodHandle,
MethodType.methodType(String.class)
);
Person person = new Person("John", 30);
MethodHandle factory = callSite.getTarget();
Supplier<String> nameExtractor = (Supplier<String>) factory.invokeExact(person);
// Create an instance of the record
System.out.println("Extracted Name: " + nameExtractor.get());
}
}
您好,由于某种原因,我无法制作一个 lambda 来调用一个人的名字并将其返回给我,我不太明白它是如何工作的,请帮忙
我必须阅读文档几次才能完全理解需要传递哪些参数。
这部分对我来说是最清晰的解释:
当调用此方法返回的
的目标时,生成的函数对象是一个类的实例,该类实现由CallSite
返回类型命名的接口,声明一个由factoryType
指定名称的方法以及interfaceMethodName
的签名。interfaceMethodType
因此,factoryType 参数是生成供应商的参数。您编写的代码是正确的;它需要一个 Person 并生成一个 String:
MethodType.methodType(Supplier.class, Person.class),
下一个参数,interfaceMethodType,必须是Supplier.get()的签名。 get() 返回一个值但不带参数,因此您需要更改此设置:
MethodType.methodType(String.class, Person.class),
对此:
MethodType.methodType(Object.class),
为什么是对象而不是字符串?因为泛型是编译器的一个技巧。 Supply 的 get() 方法始终返回 Object(就像 List.get(int) 始终返回 Object 一样)。编译器强制执行正确的转换和类型检查,以模拟泛型类型安全。
您的 MethodHandle 是正确的。关于metafactory的最后一个参数,文档说:
- 应在调用时动态强制执行的签名和返回类型。在简单的用例中,这与dynamicMethodType
相同。interfaceMethodType
因此,我们再次希望通过
MethodType.methodType(Object.class)
来支持该论点。
整个事情看起来像这样:
CallSite callSite = LambdaMetafactory.metafactory(
lookup,
"get",
MethodType.methodType(Supplier.class, Person.class),
MethodType.methodType(Object.class),
methodHandle,
MethodType.methodType(Object.class)
);