First off let me say I am maintaining someone else's poorly designed code so I am limited in how much I can change it.
Now what is happening is that they have created a series of methods that are invoked by reflection. One of those methods takes a Map as one of its arguments. At runtime this Map is implemented with a Hashtable.
Here's the problem - I get a NoSuchMethodException because it is looking for a method with Hashtable as an argument even though a Hashtable implements the Map interface. What is confusing me is that if I don't use reflection (a major design change in this case) and passed a Hashtable it would invoke the method with the Map parameter - so why doesn't it work the same way when I use reflection?
Given that I pretty much have to stick with reflection is there any way to get the method with the Map argument to get invoked when I pass it a class that implements that interface?
If you want I can mock some code up to demonstrate...
Overview. Method Parameter Reflection support was added in Java 8. Simply put, it provides support for getting the names of parameters at runtime. In this quick tutorial, we'll take a look at how to access parameter names for constructors and methods at runtime – using reflection.
You can obtain the names of the formal parameters of any method or constructor with the method java. lang. reflect.
Yes, you can pass Interface as a parameter in the function.
The enabler of the technique used to avoid the very slow reflection is the invokedynamic bytecode instruction. Briefly, invokedynamic (or “indy”) was the greatest thing introduced in Java 7 in order to pave the way for implementing dynamic languages on top of the JVM through dynamic method invocation.
If you are using getMethod(String name, Class[] parameterTypes)
from java.lang.Class
, you need to specify parameter types as expressed in the method signature of the interface (static type), not the type of the object at run-time (dynamic type).
So, for methodXyz(Map map)
, instead of:
Method m = cl.getMethod("methodXyz", new Class[]{argument.getClass()});
do this:
Method m = cl.getMethod("methodXyz", new Class[]{Map.class});
I had a similar problem. I see 2 solutions:
solution 1: you can develop a more complicated search method.
Example of an algorithm you could use :
You search with the parameter type. If the search fails (Exception), but one of the parameters has a super type (or implements an interface), you search the same method name, but with this superclass (or interface). You throw the exception only if no method is found after this search algorithm.
Note : if your methods have several parameters, be sure to verify with each possible combination of supertypes/interfaces. It can result in a quite complex search algorithm...
solution 2: another method, much easier, is to precise the types separately from the parameters. This method more verbose can be necessary if you want to use null parameters.
So, "invokeMethod(String methodName, Object[] paramters)" becomes "invokeMethod(String methodName, Class[] methodParamTypes, Object[] parameters)".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With