tow*_*owi 9 java reflection lambda java-8 method-reference
我打电话时遇到异常metafactory
.它说:
java.lang.invoke.LambdaConversionException:
Incorrect number of parameters for instance method
invokeVirtual my.ExecuteTest$AProcess.step_1:()Boolean;
0 captured parameters,
0 functional interface method parameters,
0 implementation parameters
Run Code Online (Sandbox Code Playgroud)
我不明白所有的文件LambdaMetafactory.metafactory
.我在确定正确的参数时遇到了问题:
所以它归结为以下两者之间的区别:
我的代码是这样的:
package my;
import java.lang.invoke.*;
import java.lang.reflect.Method;
public class Execute {
public interface ProcessBase {};
@FunctionalInterface
public interface Step {
Boolean apply();
}
public Step getMethodFromStepid(ProcessBase process, int stepid) {
try {
// standard reflection stuff
final MethodHandle unreflect = caller.unreflect(method);
final String mname = "step_"+stepid;
// new java8 method reference stuff
final Method method = process.getClass().getMethod(mname);
final MethodType type=MethodType.methodType(Boolean.class);
final MethodType stepType=MethodType.methodType(Step.class);
final MethodHandles.Lookup caller = MethodHandles.lookup();
final CallSite site = LambdaMetafactory.metafactory(
caller, "apply", stepType, type, unreflect, type); // damn
// convert site to my method reference
final MethodHandle factory = site.getTarget();
final Step step = (Step) factory.invoke();
return step;
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过测试
package my;
import org.junit.Test;
import static org.junit.Assert.*;
public class ExecuteTest {
private class AProcess implements Execute.ProcessBase {
public Boolean step_1() { return true; }
public Boolean step_2() { return false; }
}
@Test
public void getMethodFromStepid() throws Exception {
final AProcess process = new AProcess();
{
final Execute.Step methodRef = instance.getMethodFromStepid(process, 1);
final boolean result = methodRef.apply();
assertTrue(result);
}
{
final Execute.Step methodRef = instance.getMethodFromStepid(process, 2);
final boolean result = methodRef.apply();
assertFalse(result);
}
}
private final Execute instance = new Execute();
}
Run Code Online (Sandbox Code Playgroud)
前三个参数对lambda表达式不是特殊的,而是bootstrapinvokedynamic
指令方法的标准参数.该lookup
参数封装了调用者的上下文,invokedName
而invokedType
parameters 和parameters表示invokedynamic
指令的名称和类型.
由引导方法决定分配更多语义.因为在此上下文中,此指令的目的是生成lambda表达式实例,它将使用捕获的值并生成interface
实例.因此,invokedType
将具有反映捕获值的类型的参数类型或者对于非捕获lambdas而言是无参数的,并且具有与所需功能接口匹配的返回类型.将invokedName
用于指定的功能接口的方法名,因为它不是真正这里调用这是不寻常的,但因为被调用的名字有没有其他的意思,否则,这个参数在这里重复使用.
它samMethodType
是功能接口实现方法的签名(在字节代码级别上),instantiatedMethodType
只要与Generics不相关即可.否则,samMethodType
将受到类型擦除,而instantiatedMethodType
包含实际类型参数,例如实现aFunction<String,Integer>
invokedType
将有一个返回类型 Function
samMethodType
将会 (Object)Object
instantiatedMethodType
将会 (String)Integer
请注意,对于您的特定情况,类型基本上是正确的,但由于您要在提供的process
实例上调用目标方法,您必须将其绑定到lambda实例(您甚至没有尝试过).不幸的是,你没有LambdaConversionException
在你的问题中弄清楚你有什么样的实际问题(即你得到了),所以我之前没有注意到这个问题.
如上所述,invokedType
必须包含要作为参数类型捕获的值的类型.然后,您必须将实际process
实例传递给invoke
调用.顾名思义,invokedType
必须匹配以下类型invoke
:
public Step getMethodFromStepid(ProcessBase process, int stepid) {
try {
// standard reflection stuff
final String mname = "step_"+stepid;
final Method method = process.getClass().getMethod(mname);
// new java8 method reference stuff
final MethodType type=MethodType.methodType(Boolean.class);
// invokedType: bind process, generate Step
final MethodType stepType=MethodType.methodType(Step.class,process.getClass());
final MethodHandles.Lookup caller = MethodHandles.lookup();
final MethodHandle unreflect = caller.unreflect(method);
final CallSite site = LambdaMetafactory.metafactory(
caller, "apply", stepType, type, unreflect, type);
// convert site to my method reference
final MethodHandle factory = site.getTarget();
// pass the value to bind and get the functional interface instance
final Step step = (Step)factory.invoke(process);
return step;
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
685 次 |
最近记录: |