vda8888
vda8888

Reputation: 707

Java reflection getDeclaredMethod class check

I have a method that helps to invoke a known method

public static void invoke(Object object, Class<?> callingClass, String methodName, Object[] param)

I was able to invoke this

for (Method method : callingClass.getDeclaredMethods()) {
    if (method.getName().equals("bla")) {
        method.invoke(object, param);
    }
}

But when I tried to call

Class[] paramClass = new Class[param.length];
for (int i = 0; i < paramClass.length; i++) {
    paramClass[i] = Class.forName(param[i].getClass().getName());
}
Method method = callingClass.getDeclaredMethod(methodName, paramClass);

I encountered java.lang.NoSuchMethodException. The method that I tried to invoke is

public void bla(String[] arg, Map<String, String[]> argContext);

And I passed in my "invoke" method the above, just for the param, an array consists of a String[] object, and a Map object retrieved from Collections.unmodifiableMap(source)

I guess the problem comes from the fact that my input is UnmodifiableMap where the bla method requires a regular Map. What's the work around for this? Thanks

Upvotes: 1

Views: 1190

Answers (2)

Christian Fries
Christian Fries

Reputation: 16932

The problem is, that getDeclaredMethod does not do the polymorphism for you. You have to explicitly go though all super-classes and interfaces of your parameter(s) and check for every possible signature.

That is, for class C extends B and class B extends A you have to check for method(C c), method(B b) and method(A a) (if you find any, it can be invoked with an argument of type C).

You actually have to calculate the "distance" yourself and decide what is the best suited implementation: If you find an implementation method(B,A) and an implementation method(A,B) and you like to call it with the argument (C,C), then it is up to you to decide which method applies, i.e., you either call getDeclaredMethod(A.class, B.class) or getDeclaredMethod(B.class, A.class) and both could be invoked with your argument of type (C,C).

Upvotes: 2

fabian
fabian

Reputation: 82461

Map is an interface. Therefore every instance of a Map has a concrete class different to Map.class, and the getClass() method doesn't return Map.class. But for the Class that is actually returned, there is no method that matches the signature.


Also you may want to change

Class.forName(param[i].getClass().getName())

to

param[i].getClass()

Upvotes: 1

Related Questions