CallSite lambdaFactory = LambdaMetafactory.metafactory(
lookup,
"call",
MethodType.methodType(BiConsumer.class),
MethodType.methodType(void.class,Long.class),
lookup.findVirtual(CallClass.class, "call",
MethodType.methodType(void.class,Long.class)),
MethodType.methodType(void.class));
lambdaFactory.getTarget().invoke(callId);
private void call(Long callId){
---
}
Run Code Online (Sandbox Code Playgroud)
我收到此异常 java.lang.invoke.LambdaConversionException: 实例方法 invokeVirtual 调用的参数数量不正确:()void; 0 个捕获参数、0 个功能接口方法参数、0 个实现参数
这个调用几乎有所有错误:
\n\nCallSite lambdaFactory = LambdaMetafactory.metafactory(\xc2\xa0\xc2\xa0lookup,\xc2\xa0\xc2\xa0"call",这必须是需要实现的接口方法的名称。对于BiConsumer,这是"accept"。\xc2\xa0\xc2\xa0MethodType.methodType(BiConsumer.class),这是invokedType,它必须匹配invoke与 (10) 处的调用相匹配。\xc2\xa0\xc2\xa0MethodType.methodType(void.class,Long.class),这是在字节码级别(即类型擦除之后)实现的接口方法的签名。对于BiConsumer,这始终是MethodType.methodType(void.class, Object.class, Object.class)。\xc2\xa0\xc2\xa0lookup.findVirtual(CallClass.class, "call",\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0MethodType.methodType(void.class,Long.class)),\xc2\xa0\xc2\xa0MethodType.methodType(void.class)这是接口的特殊化,或者当接口不是通用时与 (5) 相同。无论哪种情况,参数的数量都必须与 (5) 匹配。对于您的情况,您可能希望匹配目标方法,所以它必须是MethodType.methodType(void.class, CallClass.class, Long.class).\xc2\xa0\xc2\xa0);lambdaFactory.getTarget().invoke(callId);该invoke调用必须与 (4) 中指定的invokedType签名匹配。指定的参数是要捕获的值。既然你\xe2\x80\x99已经选择实现BiConsumer,它与您的目标方法具有相同的功能签名,因此无需使用附加值。最大的问题是(4)和(10)之间的不匹配,因为它使你不清楚你真正想要实现的目标。您想callId按照invoke(callId)建议捕获现有函数还是想创建一个非捕获函数,如invokedType参数和选择BiConsumer?
对于一个简单的BiConsumer生成,固定代码如下所示:
CallSite callSite = LambdaMetafactory.metafactory(\n lookup, "accept", MethodType.methodType(BiConsumer.class), \n MethodType.methodType(void.class, Object.class, Object.class),\n lookup.findVirtual(CallClass.class,"call", MethodType.methodType(void.class,Long.class)),\n MethodType.methodType(void.class, CallClass.class, Long.class)\n);\nBiConsumer<CallClass,Long> bc = (BiConsumer<CallClass, Long>)callSite.getTarget().invoke();\nRun Code Online (Sandbox Code Playgroud)\n\n如果您想捕获现有的callId,则必须将功能接口更改为不需要第二个参数的类型。此外,您\xe2\x80\x99d 需要一个适配器,因为它LambdaMetafactory期望首先捕获参数,然后是接口方法参数。因此,由于不直接支持这一点,最简单的解决方案是BiConsumer<CallClass,Long>如上所述生成 a ,然后Consumer<CallClass> c = cc -> bc.apply(cc, callId);捕获现有的callId.
仅当您还有CallClass想要绑定的现有实例时,才可以直接执行此操作:
CallSite callSite = LambdaMetafactory.metafactory(\n lookup, "run", MethodType.methodType(Runnable.class, LambdaMF.class, Long.class), \n MethodType.methodType(void.class),\n lookup.findVirtual(LambdaMF.class, "call", MethodType.methodType(void.class,Long.class)),\n MethodType.methodType(void.class)\n);\nRunnable r = (Runnable)callSite.getTarget().invoke(callClassInstance, callId);\nRun Code Online (Sandbox Code Playgroud)\n