将方法从文件转换为LambdaExpresion

问题描述

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

我一直在尝试使用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

我已经读过post,但我不明白自己在做什么和做错什么。你能帮我吗?

[编辑] 当前错误是:

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)

解决方法

啊,是的。

您称metalambdafactory错误:

meta lambda工厂的概念是它创建了lambda工厂。
然后,使用工厂创建lambda的实际实例。

第一个MethodType用于工厂-在您的情况下,您说的是“捕获Object[]
您可能不想捕获任何内容-因此正确的MethodType是methodType(loadedMethod.class)

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

您用invokeWithArguments调用生成的MethodHandle。
由于工厂不需要其他参数,因此您不应传递它们:

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