0

Two questions regarding the MethodHandle class:

  1. Is it true that every call to invokeExact() requires type casting of the return value (except for target methods that return void or Object) ?

  2. It seems that a MethodHandle can only be bound once to a receiver. Given an arbitrary MethodHandle instance, is there any way to determine whether it has already been bound and if so, to what type?

public static void main(String[] args) throws Throwable {
    MethodHandles.Lookup lookup = MethodHandles.publicLookup();
    MethodHandle handle = lookup.bind(new Object(), "toString", MethodType.methodType(String.class));

    String s = (String) handle.invokeExact();
    System.out.println(s);

    try {
        handle.invokeExact();
    }
    catch (WrongMethodTypeException e) {
        System.out.println(e);
    }

    try {
        handle.bindTo(new Object());
    }
    catch (IllegalArgumentException e) {
        System.out.println(e);
    }
}
jaco0646
  • 15,303
  • 7
  • 59
  • 83

1 Answers1

0

You can call bindTo multiple times, but you should not. The implementation assumes you want to set the receiver, if you start using this to also set arguments you produce a more complicated handle, that is more difficult to compile into lambda forms and then potentially less efficient. I advise using MethodHandles#insertArguments instead

blackdrag
  • 6,413
  • 2
  • 26
  • 38
  • 1
    There’s no difference regarding efficiency as invoking `bindTo` on an already bound handle yields to the same internal `bindArgument` invocation as `insertArguments` does. But using `bindTo` for arguments makes the code less readable (hides the intention) and will fail for primitive type parameters. – Holger Mar 11 '14 at 13:17
  • Please explain how the code example can be modified to allow binding to a new receiver object. As the example shows, an IllegalArgumentException is thrown on the second binding attempt. Also, the ability to re-bind a handle doesn't really answer any of my questions. Is there no way to determine the receiver type that a handle is currently bound to? – jaco0646 Mar 12 '14 at 01:48
  • @Holger, then the implementation changed. Well, you should avoid multiple insertArguments calls as well and instead have a single call, since that makes the handle more easy to understand for the optimizing code of course. – blackdrag Mar 14 '14 at 19:28
  • @jaco0646 basically what bind and bindTo do is setting the first argument of the handle. In case of Object#toString(), the first argument would be the instance the toString() method is called on. Now Lookup#bind does that already. At that means you get a handle where the only available argument is already set. Thus further tries to set arguments fail. So instead you should use Lookup#findVirtual here and one that handle you can call bindTo once to get another handle, which has the only argument set already. That way you can produce different handles with different set receiver. – blackdrag Mar 14 '14 at 19:38
  • addOn: You could also use the handle from the findVirtual call and not bind or bindTo, but isntead provide the receiver as first argument in the invokeExact call. `String s = handle.invokeExact(myReceiver)` – blackdrag Mar 14 '14 at 19:39
  • 1
    @jaco0646: you need to understand that a `MethodHandle` is not just an alternative to a reflective `Method` object; it *encapsulates* the actual action. When looking at two handles, there is no difference between a handle encapsulating a no-arg method `Foo.method()` or a one-arg method `Bar.method(Foo)` that has been pre-bound to an instance of `Bar`. And it doesn’t have to be an instance method at all; a `static` method `SomeClass.x(Foo)` as well as a write operation to a `static` field of type `Foo`, will have the same signature too. – Holger Mar 17 '14 at 09:50
  • @jaco0646: The only exception is that Java 8 introduces a [way to analyze a method handle](http://download.java.net/jdk8/docs/api/java/lang/invoke/MethodHandles.Lookup.html#revealDirect-java.lang.invoke.MethodHandle-) if it is a *direct* handle (has no pre-bound arguments nor receiver) and truly represents a method. – Holger Mar 17 '14 at 09:52
  • @Holger: if I understand correctly, the answers to my two questions are _Yes_ and _No_ respectively (in Java 7). – jaco0646 Mar 18 '14 at 16:13