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来调用一个人的名字并返回给我,我不太明白它是如何工作的.

推荐答案

我不得不把the documentation读了几遍,才完全明白需要传递什么论点.

这是最清晰的解释,对我来说:

当调用从该方法返回的CallSite的目标时,产生的函数对象是一个类的实例,该类实现由返回类型factoryType命名的接口,声明具有interfaceMethodName给定的名称和interfaceMethodType给定的签名的方法.

因此,factoryType参数是产生供应商的原因.您编写的代码是正确的;它接收一个人并生成一个字符串:

MethodType.methodType(Supplier.class, Person.class),

下一个参数interfaceMethodType必须是Supplier.get()的签名.Get()返回一个值,但不接受任何参数,因此您需要更改以下内容:

MethodType.methodType(String.class, Person.class),

对此:

MethodType.methodType(Object.class),

为什么是对象而不是字符串?因为泛型是一个编译器技巧.Supplier的get()方法总是返回Object(就像List.get(Int)总是返回Object一样).编译器强制执行正确的强制转换和类型判断,以模拟泛型类型安全.

您的方法句柄是正确的.关于元工厂的最后一个参数,文档说:

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

正如Holger所指出的,最后一个参数实际上是返回类型的动态绑定,因此我们可以指定它是字符串:

CallSite callSite = LambdaMetafactory.metafactory(
    lookup,
    "get",
    MethodType.methodType(Supplier.class, Person.class),
    MethodType.methodType(Object.class),
    methodHandle,
    MethodType.methodType(String.class)
);

Java相关问答推荐

如何使用CSS为选定但未聚焦的表格行设置背景 colored颜色 ?

为什么如果数组列表中有重复项,我的代码SOMETIMES不返回true?

如何在访问完所有文件后加入所有线程?

解析Javadoc时链接的全限定类名

Exe4j创建的应用程序无法再固定在任务栏Windows 11上

放气总是压缩整个街区吗?

Lombok@Nonnull是否也对供应商有影响?

Java泛型类方法的静态返回类型是否被类型擦除?

Oj算法 MatrixR032从字符串、归一化和余弦相似度计算创建

如何使这两种方法合二为一?

记录是类的语法糖吗?

本机方法(JNI)总是编译的吗?

模拟JUnit未检测到返回字符串的方法的任何声纳覆盖

OAuth:登录后无法查看Google邮箱地址

使用同步方法中的新线程调用同步方法

没有Google Play服务,Firebase Auth无法工作

设置背景时缺少Android编辑文本下划线

如何正确使用java.time类?

睡眠在 Spring Boot 中

在java中使用SevenZip.openArchive方法后无法删除文件