0

I have a problem where I have multiple methods with identical signatures (all returning void). I want to be able to combine the methodHandles for those methods to obtain a methodHandle that will invoke each method in turn.

The only way I have worked out to do this is with guardWithTest and I have an example of how I can make it work at: https://gist.github.com/gregw/b6c926fb44fd9a45b2c5afccaf7dcbf4

but the essence of the code is: ```java

    TestMethodHandle test = new TestMethodHandle();

    MethodHandle callA = MethodHandles.lookup().findVirtual(TestMethodHandle.class,"callA", methodType(Void.TYPE, String.class, Integer.TYPE)).bindTo(test);
    MethodHandle callB = MethodHandles.lookup().findVirtual(TestMethodHandle.class,"callB", methodType(Void.TYPE, String.class, Integer.TYPE)).bindTo(test);
    MethodHandle callC = MethodHandles.lookup().findVirtual(TestMethodHandle.class,"callC", methodType(Void.TYPE, String.class, Integer.TYPE)).bindTo(test);

    MethodHandle asGuard = MethodHandles.lookup().findStatic(TestMethodHandle.class,"alwaysTrue", MethodType.methodType(Boolean.TYPE));
    MethodHandle guardA = MethodHandles.filterReturnValue(callA,asGuard);
    MethodHandle guardB = MethodHandles.filterReturnValue(callB,asGuard);
    MethodHandle guardC = MethodHandles.filterReturnValue(callC,asGuard);

    MethodHandle empty = empty(methodType(Void.TYPE, String.class, Integer.TYPE));

    MethodHandle invokeC = MethodHandles.guardWithTest(guardC,empty,empty);
    MethodHandle invokeBC = MethodHandles.guardWithTest(guardB,invokeC,empty);
    MethodHandle invokeABC = MethodHandles.guardWithTest(guardA,invokeBC,empty);

    invokeABC.invoke("chained", 2);

```

Is there an easier way to do this?

Supplemental question... should I want to do this or will it be just as fast to call the methodHandles in loop over a collection of method handles?

gregw
  • 2,354
  • 20
  • 21

1 Answers1

0

I think this might be better:

    MethodHandle callA = MethodHandles.lookup().findVirtual(TestMethodHandle.class,"callA", methodType(Void.TYPE, String.class, Integer.TYPE)).bindTo(test);
    MethodHandle callB = MethodHandles.lookup().findVirtual(TestMethodHandle.class,"callB", methodType(Void.TYPE, String.class, Integer.TYPE)).bindTo(test);
    MethodHandle callC = MethodHandles.lookup().findVirtual(TestMethodHandle.class,"callC", methodType(Void.TYPE, String.class, Integer.TYPE)).bindTo(test);

    MethodHandle foldedABC = MethodHandles.foldArguments(MethodHandles.foldArguments(callC,callB),callA);
    foldedABC.invoke("folded", 42);
gregw
  • 2,354
  • 20
  • 21
  • 1
    You might remove the `.bindTo(test)` from the first three statements and apply it once on the `foldedABC` instead. Likewise, avoid performing `MethodHandles.lookup()` three times and store the lookup object into a local variable instead. Besides that, this seems to be the simplest way to chain invocations. – Holger Oct 24 '18 at 15:48