Если вы не хотите перехватывать исключения, вы должны реализовать поиск, например
public static Optional<Method> getMethod(Class<?> decl, String name, Class<?>... arg) {
return Arrays.stream(decl.getDeclaredMethods())
.filter(m -> name.equals(m.getName()) && Arrays.equals(m.getParameterTypes(), arg))
.findAny();
}
, который вы можете использовать, например,
Optional<Method> m = getMethod(target.getClass(), methodName, typeParams);
if(!m.isPresent()) {
target = second;
m = getMethod(target.getClass(), methodName, typeParams);
}
if(m.isPresent()) try {
m.get().invoke(target, args);
}
catch (IllegalAccessException|InvocationTargetException ex) {
…
}
, хотя другие способы использования опциональнывозможны.
Вы можете испытать искушение сказать «подождите ... но это делает линейный поиск по всем объявленным методам», но никто никогда не обещал, что getDeclaredMethod(String, Class<?>...)
делает что-то лучше, чем линейный поиск,и фактически, в широко используемой эталонной реализации, это не так.Поиск, который он выполняет, имеет ту же логику, что и приведенный выше, за исключением того, что в конце выдается исключение, если совпадение не найдено.
Даже если это было сделано, например, поиск хеша, затраты на созданиеновое исключение может перевесить затраты на линейный поиск с помощью ограниченного числа объявленных методов.