How can I obtain all declared method through MethodHandles.lookup()? How can I obtain all declared fields?
What is difference betweeen MethodHandl
As Balder said both calls invoke and invokeExact do not accept arguments passed in as an array. (However, they do accept array arguments.)
int[] args = {1,1};
// handle for Math.addExact(int, int)
Object o = handle.invokeExact(1,1); // OK
Object o = handle.invoke(1,1); // OK
Object o = handle.invokeExact(args); // ERROR
Object o = handle.invoke(args); // ERROR
The error is always a wrong type exception:
java.lang.invoke.WrongMethodTypeException: cannot convert MethodHandle(int, int)int to (Object[])int
So it does not unpack the array. But passing in an array where it is required works:
// handle for Arrays.sort(int[])
handle.invokeExact(args); // OK
handle.invoke(args); // OK
As Balder said, implementing the desired behavior with invokeWithArguments() may incur a quite substantial overhead.
In order to get the desired behavior for unpacking argument lists as known from varargs, one has to turn the handle into a spreader:
// handle for Math.addExact(int, int)
handle = handle.asSpreader(int[].class, 2);
handle.invokeExact(args); // OK
handle.invoke(args); // OK
Of course, the same functionality as for explicit argument passing accounts again when the array is defined to be generic:
Object[] args = new Object[]{1,1};
// handle for Math.addExact(int, int)
handle = handle.asSpreader(int[].class, 2);
handle.invokeExact(args); // ERROR
handle.invoke(args); // OK
I have not conducted any performance comparison between the calls. For those interested, it is quite straight forward to extend this benchmark: http://rick-hightower.blogspot.de/2013/10/java-invoke-dynamic-examples-java-7.html
Essentially invokeWithArguments does similar things but does so for every call:
public Object invokeWithArguments(Object... arguments) throws Throwable {
MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length);
return invocationType.invokers().spreadInvoker(0).invokeExact(asType(invocationType), arguments);
}
So creating a spreader once and reusing it, will most likely yield similar performance as invoke and invokeExact.