Q:

Ignoring exception checking while using Method.invoke in java

In a project I am taking part in, there is a plethora of classes each implementing a method called add which all work the same way, e.g. MyVector sum = add(vector1, vector2), where vector1 and vector2 are both of type MyVector. I have no permission to modify of all the classes that have add, so I could have make them implement some interface "IAddable".
Now, I'd like to make a generic class of the form
class Summinator<TVector>
{
    Function<TVector,TVector,TVector> add;

    public Summinator()
    {
        //... somehow get the class of TVector, say cVector
        Method addMethod = cVector.getDeclaredMethod("add", new Class[] {cVector, cVector});
        add = (v1, v2) -> (TVector)addMethod.invoke(null, v1, v2);
    }

    public TVector VeryLargeSum(TVector[] hugePileOfVectors)
    {
        TVector sum = hugePileOfVectors[0];
        for (int i = 1; i < hugePileOfVectors.length; i++)
        {
            sum = add(sum, hugePileOfVectors[i]);
        }
        return sum;
    }
}

As the sum is large, I'd like to have a lambda-expression to do the work. I also make type-checking at the initiation time. However, java wants me to check for exceptions every time I invoke the method, so instead of
add = (v1, v2) -> (TVector)addMethod.Invoke(null, v1, v2);

it forces me to write something like
add = (v1, v2) -> 
{
    try {
    return add.invoke(null, v1, v2);
    } catch (IllegalAccessException e) {
         e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
};

I am afraid that this exception-checking will consume lots of machine time, whereas all the objects are in fact quite basic in their nature and the application of add is in fact a matter of a handful of flops. If it was C# and all classes in question had an overloaded + operation, I could have solved my problem with System.Linq.Expressions package, using the supported binary operations: there exception checking is not obligatory. But... I am to work in java.
Perhaps, there is some way around to at least ignore exception checking?

A:

In your class, there’s something missing. You are calling getDeclaredMethod on a cVector that is nowhere in scope. Due to type erasure, a generic class has no possibility to get that Class object of the parameterization on its own, so for this class to work correctly, there must be someone instantiating the Summinator with the actual type parameterization and passing the appropriate Class object, e.g.
Summinator<Actual> actualSumminatior = new Summinator<>(Actual.class);

The cleanest solution is to change the Summinator class to let this instantiating code pass the intended add function in the first place:
class Summinator<TVector>
{
    final BinaryOperator<TVector> add;

    public Summinator(BinaryOperator<TVector> addFunction)
    {
        add = addFunction;
    }

    public TVector VeryLargeSum(TVector[] hugePileOfVectors)
    {
        TVector sum = hugePileOfVectors[0];
        for (int i = 1; i < hugePileOfVectors.length; i++)
        {
            sum = add.apply(sum, hugePileOfVectors[i]);
        }
        return sum;
    }
}

and change the caller(s) to
Summinator<Actual> actualSumminatior = new Summinator<>(Actual::add);

That’s all.
But note that the entire operation of VeryLargeSum can be simplified to
return Arrays.stream(hugePileOfVectors).reduce(Actual::add)
    .orElseThrow(() -> new IllegalArgumentException("empty array"));

at the use site, rendering the entire Summinator obsolete.

If the calling code is an unchangeable legacy code base and you have to live with the Class input, you can generate the equivalent to method references dynamically:
class Summinator<TVector>
{
    final BinaryOperator<TVector> add;

    public Summinator(Class<TVector> cVector)
    {
        MethodHandles.Lookup l = MethodHandles.lookup();
        MethodType addSignature = MethodType.methodType(cVector, cVector, cVector);
        try
        {
            MethodHandle addMethod = l.findStatic(cVector, "add", addSignature);
            add = (BinaryOperator<TVector>)LambdaMetafactory.metafactory(l, "apply",
                  MethodType.methodType(BinaryOperator.class),
                  addSignature.erase(), addMethod, addSignature)
                .getTarget().invokeExact();
        }
        catch(RuntimeException|Error t)
        {
            throw t;
        }
        catch(Throwable t) {
            throw new IllegalArgumentException("not an appropriate type "+cVector, t);
        }
    }

    public TVector VeryLargeSum(TVector[] hugePileOfVectors)
    { // if hugePileOfVectors is truly huge, this can be changed to parallel execution
        return Arrays.stream(hugePileOfVectors).reduce(add)
            .orElseThrow(() -> new IllegalArgumentException("empty array"));
    }
}

Note that both solutions likely run faster than the Method.invoke based, but not due to the absence of exception handling in the function, but rather because invocation through Reflection is expensive in general.

