jeudi 30 août 2018

How to invoke a MethodHandle with varargs

I'm trying to replace a reflective invocation with a MethodHandle, but varargs seem to be impossible to deal with.

My reflective invoker currently looks like this:

public class Invoker {

    private final Method delegate;

    public Invoker(Method delegate) {
        this.delegate = delegate;
    }

    public Object execute(Object target, Object[] args) {
        return delegate.invoke(target, args);
    }
}

My current attempt at rewriting it looks like this (the interface the Invoker exposes has to stay the same):

public class Invoker {

    private final Method delegate;
    private final MethodHandle handle;

    public Invoker(Method delegate) {
        this.delegate = delegate;
        this.handle = MethodHandles.lookup().unreflect(delegate);
    }

    public Object execute(Object target, Object[] args) throws InvocationTargetException, IllegalAccessException {
        Object[] allArgs = merge(target, args);
        return handle.invokeWithArguments(allArgs);
    }
}

And this works just fine in most cases. But varargs break everything. E.g. have a method like:

public String test(int i, String... args) {
    return ...;
}

And the above will fail. I tried various combinations of asSpreader(), MethodHandles.explicitCastArguments(), invoke instead of invokeWithArguments etc with 0 success.

The only way I can invoke a varargs method is to provide the arguments inline and not as an array (e.g. handle.invokeWithArguments(args1, args2...)), but I can not do that and maintain the generic nature of the Invoker that it currently has.

Is this really impossible to do the way I'm trying?





Aucun commentaire:

Enregistrer un commentaire