I am experiencing a NoSuchMethodException when trying to call getMethod on a method in the same class with no arguments from a string name pulled from a hashmap. Any advice, or another way to call a method in the same class given only a String name of the method? The call to get the method is here:
if (testChoices.containsKey(K)) {
String method = testChoices.get(K);
System.out.println(method);
try {
java.lang.reflect.Method m = TST.getClass().getMethod(method);
m.invoke(testChoices.getClass());
} catch (NoSuchMethodException e1) {
// TODO Auto-generated catch block
System.out.println("No method found");
e1.printStackTrace();
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
One of the methods I am trying to call is here:
private static void testgetDomainLic() throws IOException {
And the map entry being called is here:
testChoices.put(1, "testgetDomainLic");
I think in your case you can just change getMethod
to getDeclaredMethod
. getMethod
only returns public methods.
The hiccup here is that they actually have different semantics other than whether or not they return non-public methods. getDeclaredMethod
only includes methods which are declared and not inherited.
So for example:
class Foo { protected void m() {} }
class Bar extends Foo {}
Foo actuallyBar = new Bar();
// This will throw NoSuchMethodException
// because m() is declared by Foo, not Bar:
actuallyBar.getClass().getDeclaredMethod("m");
In the worst case like this, you have to loop through all declared methods, like this:
Class<?> c = obj.getClass();
do {
for (Method m : c.getDeclaredMethods())
if (isAMatch(m))
return m;
} while ((c = c.getSuperclass()) != null);
Or accounting for interfaces (mostly because they can declare static methods now):
List<Class<?>> classes = new ArrayList<>();
for (Class<?> c = obj.getClass(); c != null; c = c.getSuperclass())
classes.add(c);
Collections.addAll(classes, obj.getClass().getInterfaces());
Method m = classes.stream()
.map(Class::getDeclaredMethods)
.flatMap(Arrays::stream)
.filter(this::isAMatch)
.findFirst()
.orElse(null);
And as a side note, you probably don't need to call m.setAccessible(true)
, because you're invoking it from within the class that declares it. This is necessary, though, in other contexts.