I get an exception when I call metafactory
. It says:
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
I do not understand all from the documentation of LambdaMetafactory.metafactory
. I have problems figuring out the correct parameters:
- MethodHandles.Lookup caller -- thats easy
- String invokedName -- I am fairly certain here
- MethodType invokedType -- whats this?
- MethodType samMethodType -- err... not sure here
- MethodHandle implMethod -- that's fine
- MethodType instantiatedMethodType -- whats this, again? Second time?
So it boils down to what are the differences between:
- MethodType invokedType
- MethodType samMethodType
- MethodType instantiatedMethodType
My code is like this:
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);
}
}
}
with the tests
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();
}
Aucun commentaire:
Enregistrer un commentaire