首页 > 解决方案 > 将方法从文件转换为 LambdaExpression

问题描述

我正在尝试将方法(从文件中读取)转换为 lambda 表达式,因此我可以测量执行该方法所需的时间,而忽略慢速 Method.invoke(...) 函数。

我一直在尝试使用 实现我的目标LambdaMetafactory,但老实说,我已经阅读了很多关于如何做到这一点的问题和解释,以至于我什至不知道我在做什么了。

假设参数和方法构造良好并且(这是棘手的部分)我必须动态处理涉及不同数量和类型参数的多个选项:

Object[] parameters = ...;
Method metodin = anotherClass.getMethod();

以及界面(对不起名称,我稍后会更改它):

@FunctionalInterface
interface loadedMethod {
    Object execute(Object[] params);
}

这是尝试使用 lambda 执行该方法的代码:

MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle mh = lookup.unreflect(metodin);

CallSite callsite = LambdaMetafactory.metafactory(
       lookup,
       "execute",
       MethodType.methodType(loadedMethod.class),
       mh.type(),
       mh,
       mh.type()
);
loadedMethod loadedMethod = (loadedMethod) callsite.getTarget().invokeExact();
System.out.println("OUTPUT: " + loadedMethod.execute(parameters)); //Error occurs here

我读过这篇文章,我不明白我在做什么好和错。你能帮我吗?

[编辑] 当前错误是:

java.lang.invoke.LambdaConversionException: Incorrect number of parameters for static method invokeStatic Example.myFunction:(int[],int,int)int; 1 captured parameters, 3 functional interface method parameters, 3 implementation parameters
    at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:214)
    at java.base/java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:328)
    at optimex.ObjectCallable.call(ObjectCallable.java:60)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)

标签: javamethodslambdamethodhandlelambda-metafactory

解决方案


啊,是的。

你调用 metalambdafactory 错误:

元 lambda 工厂的概念是它创建了一个 lambda 工厂。
然后,您可以使用工厂创建 lambda 的实际实例。

第一个MethodType是针对工厂的-在您的情况下,您说“捕获一个Object[]
您可能不想捕获任何东西-所以正确的 MethodType 是methodType(loadedMethod.class).

CallSite callsite = LambdaMetafactory.metafactory(
       lookup,
       "execute",
       MethodType.methodType(loadedMethod.class),
       mh.type(),
       mh,
       mh.type()
);

您使用 调用生成的 MethodHandle invokeWithArguments
由于工厂不需要额外的参数,你不应该传递它们:

loadedMethod loadedMethod = (loadedMethod) callsite.getTarget().invokeExact();

推荐阅读